提问人:user2950720 提问时间:12/14/2022 最后编辑:Peter Seligeruser2950720 更新时间:12/21/2022 访问量:107
如何解析XML并以自定义方式再次序列化它,将空元素显示为扩展标签?
How to parse XML and serialize it again in a custom way which shows empty elements as expanded tags?
问:
我有以下可以是动态的
const data = '<users>
<user>
<firstname>test</firstname>
<lastname />
<age />
</user>
</users>'
我想找到它用 a 和 expand 关闭的每个实例,例如变成 />
<age />
<age></age>
显然,我可以使用命名标签来做到这一点,例如
data = data.replaceAll("age />", "age></age>")
但是,对于我不知道名称的标签,我如何在全球范围内执行此操作?
答:
0赞
Peter Seliger
12/15/2022
#1
从上面的评论中......
“OP 可以通过 DOMParser.parseFromString 创建一个 XMLDocument,例如
const doc = (new DOMParser).parseFromString(data, 'application/xml');
。但是,OP 需要编写自己的序列化功能,因为
XMLSerializer
的serializeToString
方法会将每个空节点序列化为其空标记表示形式。
下一个提供的示例代码附带一个自定义序列化程序,以证明建议的方法可以毫不费力地实现。
const data = `<users lang="en">
<user uuid="1232-3965-6923-2887">
<firstname>test</firstname>
<lastname/>
<age type="integer"/>
</user>
</users>`;
const xmlDoc = (new DOMParser).parseFromString(data, 'application/xml');
const xmlSerializerMarkup = (new XMLSerializer).serializeToString(xmlDoc);
const documentElementMarkup = xmlDoc.documentElement.outerHTML;
console.log('originally provided markup...\n', data);
console.log('XMLSerializer markup...\n', xmlSerializerMarkup);
console.log('documentElement markup...\n', documentElementMarkup);
function serialize(elmNode, indention = '') {
const { nodeName, childElementCount } = elmNode;
let currentMarkup = elmNode
.getAttributeNames()
.reduce((markup, attrName) => [
markup,
' ',
attrName,
'="',
elmNode.getAttribute(attrName),
'"',
].join(''), `${ indention }<${ nodeName }`);
if (childElementCount === 0) {
const { textContent } = elmNode;
if (textContent === '') {
// entirely empty element node.
// do not implement/support the empty tag style.
currentMarkup = currentMarkup + `><\/${ nodeName }>`;
} else {
currentMarkup = [
currentMarkup,
'>',
textContent,
`<\/${ nodeName }>`,
].join('');
}
} else {
let nestedMarkup = '';
[...elmNode.children]
.forEach(childElement => {
nestedMarkup = [
nestedMarkup,
serialize(childElement, (indention + ' ')),
].join('\n');
});
currentMarkup = [
currentMarkup,
nestedMarkup,
].join('>') + `\n${ indention }<\/${ nodeName }>`;
}
return currentMarkup;
}
const customSerializerMarkup = serialize(xmlDoc.documentElement);
console.log('custom serializer markup...\n', customSerializerMarkup);
.as-console-wrapper { min-height: 100%!important; top: 0; }
0赞
skreutzer
12/16/2022
#2
您是否介意使用/改编像 JsStAX 这样的东西(完全披露:我的一个小移植项目,用于在 JavaScript 中实现 Java 的 XML 流式处理 API)?
好处是,使用外部事件循环,您可以很好地控制要生成的输出,并且不会遇到XML格式的任何变化。
它是否太重,是否缺少必需/所需的功能(因为它不是 XML 功能完整的),反对许可证?但是,除了许多可能的改进或其他可能更好的解决方案之外,这项工作确实如此。
评论
<age />
<age></age>
y
<?xml version="1.0" encoding="UTF-8"?><x><y a="/>" b='/>' c="'" d='"' e=">"></y></x>