使用 StAX 将 XML 元素提取为包含属性命名空间的字符串
Extract XML element as string including attribute namespace using StAX
给定以下 XML 字符串
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:a="http://a" xmlns:b="http://b">
<a:element b:attribute="value">
<subelement/>
</a:element>
</root>
我想将元素 a:element
提取为 XML 字符串,同时使用 StAX 保留已使用的命名空间。所以我希望
<?xml version="1.0" encoding="UTF-8"?>
<a:element xmlns:a="http://a" xmlns:b="http://b" b:attribute="value">
<subelement/>
</a:element>
按照 and 这样的回答,我已经有了以下代码:
final ByteArrayInputStream inputStream = new ByteArrayInputStream(inputString.getBytes(StandardCharsets.UTF_8));
final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
final XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStream);
xmlStreamReader.nextTag();
xmlStreamReader.nextTag();
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
final Transformer transformer = transformerFactory.newTransformer();
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
transformer.transform(new StAXSource(xmlStreamReader), new StreamResult(outputStream));
final String outputString = outputStream.toString(StandardCharsets.UTF_8.name());
但是,结果不包含属性 b:attribute
的命名空间 http://b
(使用 Java 8 的默认 StAX 解析器或 Aalto [=30 的 StAX 解析器=]):
<?xml version="1.0" encoding="UTF-8"?>
<a:element xmlns:a="http://a" b:attribute="value">
<subelement/>
</a:element>
如何使用 StAX 获得预期结果?
使用 xslt 转换来执行此操作会更简洁。您已经在使用身份转换器来执行输出 - 只需将其设置为复制目标元素而不是所有内容:
public static void main(String[] args) throws TransformerException {
String inputString =
"<root xmlns:a='http://a' xmlns:b='http://b'>" +
" <a:element b:attribute='value'>" +
" <subelement/>" +
" </a:element>" +
"</root>";
String xslt =
"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:a='http://a'>" +
" <xsl:template match='/root'>" +
" <xsl:copy-of select='a:element'/>" +
" </xsl:template>" +
"</xsl:stylesheet>";
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(new StringReader(xslt)));
transformer.transform(new StreamSource(new StringReader(inputString)), new StreamResult(System.out));
}
您正在使用的 stax 子树转换依赖于 jdk 附带的转换器的一些不确定行为。当我用 Saxon transformer 尝试时它不起作用(它抱怨尾随 </root>
)。
给定以下 XML 字符串
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:a="http://a" xmlns:b="http://b">
<a:element b:attribute="value">
<subelement/>
</a:element>
</root>
我想将元素 a:element
提取为 XML 字符串,同时使用 StAX 保留已使用的命名空间。所以我希望
<?xml version="1.0" encoding="UTF-8"?>
<a:element xmlns:a="http://a" xmlns:b="http://b" b:attribute="value">
<subelement/>
</a:element>
按照 and 这样的回答,我已经有了以下代码:
final ByteArrayInputStream inputStream = new ByteArrayInputStream(inputString.getBytes(StandardCharsets.UTF_8));
final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
final XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStream);
xmlStreamReader.nextTag();
xmlStreamReader.nextTag();
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
final Transformer transformer = transformerFactory.newTransformer();
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
transformer.transform(new StAXSource(xmlStreamReader), new StreamResult(outputStream));
final String outputString = outputStream.toString(StandardCharsets.UTF_8.name());
但是,结果不包含属性 b:attribute
的命名空间 http://b
(使用 Java 8 的默认 StAX 解析器或 Aalto [=30 的 StAX 解析器=]):
<?xml version="1.0" encoding="UTF-8"?>
<a:element xmlns:a="http://a" b:attribute="value">
<subelement/>
</a:element>
如何使用 StAX 获得预期结果?
使用 xslt 转换来执行此操作会更简洁。您已经在使用身份转换器来执行输出 - 只需将其设置为复制目标元素而不是所有内容:
public static void main(String[] args) throws TransformerException {
String inputString =
"<root xmlns:a='http://a' xmlns:b='http://b'>" +
" <a:element b:attribute='value'>" +
" <subelement/>" +
" </a:element>" +
"</root>";
String xslt =
"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:a='http://a'>" +
" <xsl:template match='/root'>" +
" <xsl:copy-of select='a:element'/>" +
" </xsl:template>" +
"</xsl:stylesheet>";
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(new StringReader(xslt)));
transformer.transform(new StreamSource(new StringReader(inputString)), new StreamResult(System.out));
}
您正在使用的 stax 子树转换依赖于 jdk 附带的转换器的一些不确定行为。当我用 Saxon transformer 尝试时它不起作用(它抱怨尾随 </root>
)。