javascript로 XML을 예쁘게 인쇄
프리 프린트하고 싶은 비인덴트 XML을 나타내는 문자열이 있습니다.예를 들어,
<root><node/></root>
다음이 되어야 합니다.
<root>
<node/>
</root>
구문 강조 표시는 필수 사항이 아닙니다.이 문제를 해결하기 위해 나는 먼저 캐리지 리턴과 화이트 스페이스를 추가하기 위해 XML을 변환한 다음 프리태그를 사용하여 XML을 출력합니다. 나는 새 행과 화이트 스페이스를 추가하기 위해 다음과 같은 함수를 썼습니다.
function formatXml(xml) {
var formatted = '';
var reg = /(>)(<)(\/*)/g;
xml = xml.replace(reg, '$1\r\n$2$3');
var pad = 0;
jQuery.each(xml.split('\r\n'), function(index, node) {
var indent = 0;
if (node.match( /.+<\/\w[^>]*>$/ )) {
indent = 0;
} else if (node.match( /^<\/\w/ )) {
if (pad != 0) {
pad -= 1;
}
} else if (node.match( /^<\w[^>]*[^\/]>.*$/ )) {
indent = 1;
} else {
indent = 0;
}
var padding = '';
for (var i = 0; i < pad; i++) {
padding += ' ';
}
formatted += padding + node + '\r\n';
pad += indent;
});
return formatted;
}
그런 다음 이 함수를 다음과 같이 부릅니다.
jQuery('pre.formatted-xml').text(formatXml('<root><node1/></root>'));
이것은 저에게 완벽하게 잘 작동하지만, 이전 기능을 쓰는 동안 더 좋은 방법이 있을 것이라 생각했습니다.그래서 제 질문은 XML 문자열을 HTML 페이지에 예쁘게 인쇄할 수 있는 더 좋은 방법을 알고 계십니까?작업을 수행할 수 있는 모든 자바스크립트 프레임워크 및/또는 플러그인을 환영합니다.저의 유일한 요구사항은 이것이 고객측에서 이루어지는 것입니다.
이는 서드파티 립 없이 네이티브 자바스크립트 도구를 사용하여 @Dimtre Novatchev의 답변을 확장할 수 있습니다.
var prettifyXml = function(sourceXml)
{
var xmlDoc = new DOMParser().parseFromString(sourceXml, 'application/xml');
var xsltDoc = new DOMParser().parseFromString([
// describes how we want to modify the XML - indent everything
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">',
' <xsl:strip-space elements="*"/>',
' <xsl:template match="para[content-style][not(text())]">', // change to just text() to strip space in text nodes
' <xsl:value-of select="normalize-space(.)"/>',
' </xsl:template>',
' <xsl:template match="node()|@*">',
' <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>',
' </xsl:template>',
' <xsl:output indent="yes"/>',
'</xsl:stylesheet>',
].join('\n'), 'application/xml');
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsltDoc);
var resultDoc = xsltProcessor.transformToDocument(xmlDoc);
var resultXml = new XMLSerializer().serializeToString(resultDoc);
return resultXml;
};
console.log(prettifyXml('<root><node/></root>'));
출력:
<root>
<node/>
</root>
@jat255에서 지적한 바와 같이 firefox에서는 예쁜 인쇄를 지원하지 않습니다.이것은 크롬, 오페라 그리고 아마도 나머지 웹킷 기반 브라우저에서만 작동하는 것으로 보입니다.
질문의 본문에서 HTML 형식의 결과가 아닌 문자열 결과가 예상된다는 인상을 받습니다.
만약 그렇다면, 이를 달성하는 가장 간단한 방법은 다음과 같은 명령을 사용하여 ID 변환을 통해 XML 문서를 처리하는 것입니다.
<xsl:스타일시트 버전="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform "><xsl:outputomit-xml-declar화="yes" endent="yes"/><xsl:template match="노드 ()|@*"><xsl:copy><xsl:apply-templates 선택="노드 ()|@*"/></xsl:copy></xsl: template></xsl:스타일시트>
제공된 XML 문서에 이 변환을 적용할 때:
<root><node/></root>
대부분의 XSLT 프로세서(.)NET XslCompiled Transform, Saxon 6.5.4 및 Saxon 9.0.0.2, AltovaXML)에서 원하는 결과를 제공합니다.
<뿌리><노드 /></root>
유사한 요구 사항이 있을 때 이 스레드를 찾았지만 OP의 코드를 다음과 같이 단순화했습니다.
function formatXml(xml, tab) { // tab = optional indent value, default is tab (\t)
var formatted = '', indent= '';
tab = tab || '\t';
xml.split(/>\s*</).forEach(function(node) {
if (node.match( /^\/\w/ )) indent = indent.substring(tab.length); // decrease indent by one 'tab'
formatted += indent + '<' + node + '>\r\n';
if (node.match( /^<?\w[^>]*[^\/]$/ )) indent += tab; // increase indent
});
return formatted.substring(1, formatted.length-3);
}
저한테 효과가 있어요!
efnx clckclcks의 javascript 기능을 약간 수정했습니다.서식을 공백에서 탭으로 변경했지만 가장 중요한 것은 텍스트를 한 줄에 유지할 수 있도록 허용했습니다.
var formatXml = this.formatXml = function (xml) {
var reg = /(>)\s*(<)(\/*)/g; // updated Mar 30, 2015
var wsexp = / *(.*) +\n/g;
var contexp = /(<.+>)(.+\n)/g;
xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
var pad = 0;
var formatted = '';
var lines = xml.split('\n');
var indent = 0;
var lastType = 'other';
// 4 types of tags - single, closing, opening, other (text, doctype, comment) - 4*4 = 16 transitions
var transitions = {
'single->single': 0,
'single->closing': -1,
'single->opening': 0,
'single->other': 0,
'closing->single': 0,
'closing->closing': -1,
'closing->opening': 0,
'closing->other': 0,
'opening->single': 1,
'opening->closing': 0,
'opening->opening': 1,
'opening->other': 1,
'other->single': 0,
'other->closing': -1,
'other->opening': 0,
'other->other': 0
};
for (var i = 0; i < lines.length; i++) {
var ln = lines[i];
// Luca Viggiani 2017-07-03: handle optional <?xml ... ?> declaration
if (ln.match(/\s*<\?xml/)) {
formatted += ln + "\n";
continue;
}
// ---
var single = Boolean(ln.match(/<.+\/>/)); // is this line a single tag? ex. <br />
var closing = Boolean(ln.match(/<\/.+>/)); // is this a closing tag? ex. </a>
var opening = Boolean(ln.match(/<[^!].*>/)); // is this even a tag (that's not <!something>)
var type = single ? 'single' : closing ? 'closing' : opening ? 'opening' : 'other';
var fromTo = lastType + '->' + type;
lastType = type;
var padding = '';
indent += transitions[fromTo];
for (var j = 0; j < indent; j++) {
padding += '\t';
}
if (fromTo == 'opening->closing')
formatted = formatted.substr(0, formatted.length - 1) + ln + '\n'; // substr removes line break (\n) from prev loop
else
formatted += padding + ln + '\n';
}
return formatted;
};
개인적으로 구글 코드 프리티파이는 다음과 같은 기능은 다음과 같습니다.
prettyPrintOne('<root><node1><root>', 'xml')
아니면 다른 js 함수를 사용하고 싶으시다면 다린의 함수를 수정했습니다.
var formatXml = this.formatXml = function (xml) {
var reg = /(>)(<)(\/*)/g;
var wsexp = / *(.*) +\n/g;
var contexp = /(<.+>)(.+\n)/g;
xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
var pad = 0;
var formatted = '';
var lines = xml.split('\n');
var indent = 0;
var lastType = 'other';
// 4 types of tags - single, closing, opening, other (text, doctype, comment) - 4*4 = 16 transitions
var transitions = {
'single->single' : 0,
'single->closing' : -1,
'single->opening' : 0,
'single->other' : 0,
'closing->single' : 0,
'closing->closing' : -1,
'closing->opening' : 0,
'closing->other' : 0,
'opening->single' : 1,
'opening->closing' : 0,
'opening->opening' : 1,
'opening->other' : 1,
'other->single' : 0,
'other->closing' : -1,
'other->opening' : 0,
'other->other' : 0
};
for (var i=0; i < lines.length; i++) {
var ln = lines[i];
var single = Boolean(ln.match(/<.+\/>/)); // is this line a single tag? ex. <br />
var closing = Boolean(ln.match(/<\/.+>/)); // is this a closing tag? ex. </a>
var opening = Boolean(ln.match(/<[^!].*>/)); // is this even a tag (that's not <!something>)
var type = single ? 'single' : closing ? 'closing' : opening ? 'opening' : 'other';
var fromTo = lastType + '->' + type;
lastType = type;
var padding = '';
indent += transitions[fromTo];
for (var j = 0; j < indent; j++) {
padding += ' ';
}
formatted += padding + ln + '\n';
}
return formatted;
};
여기에 주어진 모든 자바스크립트 함수는 끝 태그 '>'와 시작 태그 '<' 사이에 지정되지 않은 공백이 있는 xml 문서에서는 작동하지 않습니다.그것들을 고치기 위해서는, 함수들의 첫번째 줄을 바꾸기만 하면 됩니다.
var reg = /(>)(<)(\/*)/g;
타고
var reg = /(>)\s*(<)(\/*)/g;
stub 노드(document.createElement('div'))를 생성하거나 라이브러리 등가물을 사용하여 xml 문자열로 채웁니다(내부를 통해).HTML) 및 루트가 없는 경우 루트 요소/또는 스터브 요소에 대해 단순 재귀 함수를 호출합니다.함수는 모든 자식 노드를 호출합니다.
그런 다음 구문을 강조하여 마크업이 잘 형성되었는지 확인할 수 있습니다(내부를 통해 추가할 때 브라우저에서 자동으로 수행됨).HTML) 등.코드도 그렇게 많지 않고 아마 충분히 빠를 겁니다.
JavaScript 솔루션을 찾고 계신다면 http://prettydiff.com/ ?m=beautify의 Pretty Diff 툴에서 코드를 가져오시면 됩니다.
s 파라미터를 사용하여 다음과 같은 도구로 파일을 보낼 수도 있습니다. http://prettydiff.com/ ?m=beautify&s=https://stackoverflow.com/
xml-beautify로 꽤 포맷된 xml을 얻을 수 있습니다.
var prettyXmlText = new XmlBeautify().beautify(xmlText,
{indent: " ",useSelfClosingElement: true});
들여쓰기:백자 같은 indent 패턴
selfClosingElement: true=> 요소가 비어있는 경우 self-closing 요소를 사용합니다.
원본(이전)
<?xml version="1.0" encoding="utf-8"?><example version="2.0">
<head><title>Original aTitle</title></head>
<body info="none" ></body>
</example>
미화(이후)
<?xml version="1.0" encoding="utf-8"?>
<example version="2.0">
<head>
<title>Original aTitle</title>
</head>
<body info="none" />
</example>
현재 프로젝트에서는 별도의 라이브러리 없이 XML을 예쁘게 하고 색상을 조정해야 했습니다.다음의 자체 포함 코드는 꽤 잘 작동합니다.
function formatXml(xml,colorize,indent) {
function esc(s){return s.replace(/[-\/&<> ]/g,function(c){ // Escape special chars
return c==' '?' ':'&#'+c.charCodeAt(0)+';';});}
var sm='<div class="xmt">',se='<div class="xel">',sd='<div class="xdt">',
sa='<div class="xat">',tb='<div class="xtb">',tc='<div class="xtc">',
ind=indent||' ',sz='</div>',tz='</div>',re='',is='',ib,ob,at,i;
if (!colorize) sm=se=sd=sa=sz='';
xml.match(/(?<=<).*(?=>)|$/s)[0].split(/>\s*</).forEach(function(nd){
ob=('<'+nd+'>').match(/^(<[!?\/]?)(.*?)([?\/]?>)$/s); // Split outer brackets
ib=ob[2].match(/^(.*?)>(.*)<\/(.*)$/s)||['',ob[2],'']; // Split inner brackets
at=ib[1].match(/^--.*--$|=|('|").*?\1|[^\t\n\f \/>"'=]+/g)||['']; // Split attributes
if (ob[1]=='</') is=is.substring(ind.length); // Decrease indent
re+=tb+tc+esc(is)+tz+tc+sm+esc(ob[1])+sz+se+esc(at[0])+sz;
for (i=1;i<at.length;i++) re+=(at[i]=="="?sm+"="+sz+sd+esc(at[++i]):sa+' '+at[i])+sz;
re+=ib[2]?sm+esc('>')+sz+sd+esc(ib[2])+sz+sm+esc('</')+sz+se+ib[3]+sz:'';
re+=sm+esc(ob[3])+sz+tz+tz;
if (ob[1]+ob[3]+ib[2]=='<>') is+=ind; // Increase indent
});
return re;
}
https://jsfiddle.net/dkb0La16/ 참조
Or just print out the special HTML characters?
Ex: <xmlstuff> 	<node /> </xmlstuff>
	 Horizontal tab
Line feed
XML 스펙트럼 포맷 XML은 속성 들여쓰기를 지원하며 XML 및 내장된 XPath 식에 대해 구문 강조 표시를 수행합니다.
XMLSpectrum은 XSLT 2.0으로 코딩된 오픈 소스 프로젝트이므로 Saxon-HE(권장)와 같은 프로세서 또는 Saxon-CE를 사용하여 클라이언트 측에서 이 서버 측을 실행할 수 있습니다.
XML 스펙트럼은 아직 브라우저에서 실행할 수 있도록 최적화되어 있지 않으므로 이 서버측에서 실행하는 것이 좋습니다.
여기 xml을 포맷하는 다른 함수가 있습니다.
function formatXml(xml){
var out = "";
var tab = " ";
var indent = 0;
var inClosingTag=false;
var dent=function(no){
out += "\n";
for(var i=0; i < no; i++)
out+=tab;
}
for (var i=0; i < xml.length; i++) {
var c = xml.charAt(i);
if(c=='<'){
// handle </
if(xml.charAt(i+1) == '/'){
inClosingTag = true;
dent(--indent);
}
out+=c;
}else if(c=='>'){
out+=c;
// handle />
if(xml.charAt(i-1) == '/'){
out+="\n";
//dent(--indent)
}else{
if(!inClosingTag)
dent(++indent);
else{
out+="\n";
inClosingTag=false;
}
}
}else{
out+=c;
}
}
return out;
}
var formatXml = this.formatXml = function (xml) {
var reg = /(>)(<)(\/*)/g;
var wsexp = / *(.*) +\n/g;
var contexp = /(<.+>)(.+\n)/g;
xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
var pad = 0;
var formatted = '';
var lines = xml.split('\n');
var indent = 0;
var lastType = 'other';
xml 포맷은 xml을 구문 분석하여 들여쓰기를 위해 돔 트리의 텍스트 노드를 추가하거나 변경한 다음 dom을 xml로 다시 직렬화함으로써 수행할 수 있습니다.
https://jsonbrowser.sourceforge.io/formatxml.js 에서 formatxml 기능을 확인하십시오. Xml 탭 아래에 있는 https://jsonbrowser.sourceforge.io/ 에서 실행 중인 기능을 확인할 수 있습니다.
아래는 간소화된 코드입니다.formatxml.js는 오류 검사, 주석 제거(선택 사항), 매개 변수로 들여쓰기를 추가하고 부모 노드 사이의 공백 없는 텍스트를 처리합니다.
const parser = new DOMParser();
const serializer = new XMLSerializer();
function formatXml(xml) {
let xmlDoc = parser.parseFromString(xml, 'application/xml');
let rootElement = xmlDoc.documentElement;
indentChildren(xmlDoc, rootElement, "\n", "\n ");
xml = serializer.serializeToString(xmlDoc);
return xml;
}
function indentChildren(xmlDoc, node, prevPrefix, prefix) {
let children = node.childNodes;
let i;
let prevChild = null;
let prevChildType = 1;
let child = null;
let childType;
for (i = 0; i < children.length; i++) {
child = children[i];
childType = child.nodeType;
if (childType != 3) {
if (prevChildType == 3) {
// Update prev text node with correct indent
prevChild.nodeValue = prefix;
} else {
// Create and insert text node with correct indent
let textNode = xmlDoc.createTextNode(prefix);
node.insertBefore(textNode, child);
i++;
}
if (childType == 1) {
let isLeaf = child.childNodes.length == 0 || child.childNodes.length == 1 && child.childNodes[0].nodeType != 1;
if (!isLeaf) {
indentChildren(xmlDoc, child, prefix, prefix + " ");
}
}
}
prevChild = child;
prevChildType =childType;
}
if (child != null) {
// Previous level indentation after last child
if (childType == 3) {
child.nodeValue = prevPrefix;
} else {
let textNode = xmlDoc.createTextNode(prevPrefix);
node.append(textNode);
}
}
}
참조 : https://www.w3schools.com/XML/dom_intro.asp
var reg = /(>)\s*(<)(\/*)/g;
xml = xml.replace(/\r|\n/g, ''); //deleting already existing whitespaces
xml = xml.replace(reg, '$1\r\n$2$3');
예쁜 인쇄를 위해 위의 방법을 사용한 다음 jquery text() 방법을 사용하여 div에 추가합니다.예를 들어 divis의 idxmldiv
다음을 사용합니다.
$("#xmldiv").text(formatXml(youXmlString));
Saxon-JS 클라이언트 측을 사용할 수도 있습니다.
<script src="SaxonJS/SaxonJS2.js"></script>
<script>
let myXML = `<root><node/></root>`;
SaxonJS.getResource({
text: myXML.replace(`xml:space="preserve"`, ''),
type: "xml"
}).then(doc => {
const output = SaxonJS.serialize(doc, {method: "xml", indent: true, "omit-xml-declaration":true});
console.log(output);
})
</script>
Saxon-JS 설치 클라이언트 측
색슨-JS 다운로드 페이지
이것은 노드를 개체로 만드는 것과 관련될 수 있지만, 꽤 형식이 지정된 xml을 내보내는 것을 완전히 제어할 수 있습니다.
다음은 새 줄 구분 기호 "\n"으로 가입할 수 있는 줄의 문자열 배열을 반환합니다.
/**
* The child of an XML node can be raw text or another xml node.
*/
export type PossibleNode = XmlNode | string;
/**
* Base XML Node type.
*/
export interface XmlNode {
tag: string;
attrs?: { [key: string]: string };
children?: PossibleNode[];
}
/**
* Exports the given XML node to a string array.
*
* @param node XML Node
* @param autoClose Auto close the tag
* @param indent Indentation level
* @returns String array
*/
export function xmlNodeToString(
node: XmlNode,
autoClose: boolean = true,
indent: number = 0
): string[] {
const indentStr = " ".repeat(indent);
const sb: string[] = [];
sb.push(`${indentStr}<${node.tag}`);
if (node.attrs) {
for (const key in node.attrs) {
sb.push(`${indentStr} ${key}="${node.attrs[key]}"`);
}
}
if (node.children) {
if (node.children.length === 1 && typeof node.children[0] === "string") {
sb[sb.length - 1] += ">" + node.children[0];
} else {
sb.push(`${indentStr}>`);
for (const child of node.children) {
if (typeof child === "string") {
sb.push(`${indentStr} ${child}`);
} else {
const lines = xmlNodeToString(child, autoClose, indent + 1);
sb.push(...lines.map((line) => `${indentStr} ${line}`));
}
}
}
if (autoClose) {
if (node.children.length === 1 && typeof node.children[0] === "string") {
sb[sb.length - 1] += `</${node.tag}>`;
} else {
sb.push(`${indentStr}</${node.tag}>`);
}
}
} else {
if (autoClose) {
sb.push(`${indentStr}/>`);
} else {
sb.push(`${indentStr}>`);
}
}
return sb;
}
주요 내용에 대한 업데이트 감사: https://gist.github.com/rodydavis/acd609560ab0416b60681fddabc43eee
XML-to-json 라이브러리에 메서드가 있습니다.formatXml(xml).
저는 그 프로젝트의 관리자입니다.
var prettyXml = formatXml("<a><b/></a>");
// <a>
// <b/>
// </a>
이 버전은 다른 사람들에게 유용할지도 모릅니다. 누군가가 같은 코드를 가지고 있는 String Builder Saw를 사용하는 것입니다.
public String FormatXml(String xml, String tab)
{
var sb = new StringBuilder();
int indent = 0;
// find all elements
foreach (string node in Regex.Split(xml,@">\s*<"))
{
// if at end, lower indent
if (Regex.IsMatch(node, @"^\/\w")) indent--;
sb.AppendLine(String.Format("{0}<{1}>", string.Concat(Enumerable.Repeat(tab, indent).ToArray()), node));
// if at start, increase indent
if (Regex.IsMatch(node, @"^<?\w[^>]*[^\/]$")) indent++;
}
// correct first < and last > from the output
String result = sb.ToString().Substring(1);
return result.Remove(result.Length - Environment.NewLine.Length-1);
}
언급URL : https://stackoverflow.com/questions/376373/pretty-printing-xml-with-javascript
'sourcecode' 카테고리의 다른 글
로보카피가 파일을 덮어쓰도록 하려면 어떻게 해야 합니까? (0) | 2023.11.05 |
---|---|
사용되지 않는 명령줄 인수 오류를 비활성화하지 않고 clang으로 침묵시키는 방법은 무엇입니까? (0) | 2023.11.05 |
Excel에서 csv 빈 행 문제 발생 (0) | 2023.11.05 |
Swift 4에서 Json 문자열을 Json 개체로 변환 (0) | 2023.10.31 |
std::string의 컨텍스트에서 약자 SSO의 의미 (0) | 2023.10.31 |