gpt4 book ai didi

dom - 如何通过 DOM 在 xml 文档中插入 schemalocation

转载 作者:行者123 更新时间:2023-12-01 16:53:00 26 4
gpt4 key购买 nike

我使用 JAXP 创建一个 xml 文档并搜索插入 schemalocation 的方法。目前我的应用程序生成:

<?xml version="1.0" encoding="UTF-8"?>
<root>
...
</root>

但我需要:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="namespaceURL"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="namespaceURL pathToMySchema.xsd">
...
</root>

我的代码:

StreamResult result = new StreamResult(writer);
Document doc = getDocument();

Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.METHOD, "xml");
trans.setOutputProperty(OutputKeys.VERSION, "1.0");
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

DOMSource source = new DOMSource(depl.getAsElement(doc));
trans.transform(source, result);

感谢您的宝贵时间,
卡斯滕

最佳答案

在 XML 数据模型中, namespace 节点实际上不是从父元素读取的,但每个元素都有自己的 namespace 节点。因此,简单地向根元素添加新的默认命名空间是行不通的,但会产生这样的文档

<root xmlns="namespaceURL">
<child xmlns=""/>
...
</root>

请注意子元素上出现的空默认命名空间 xmlns=""。实际上需要做的是修改每个节点的命名空间,或者使用所需的默认命名空间创建一个新文档,并将旧文档的内容、元素和属性名称等复制到新文档中。这些可以通过递归地浏览原始文档来完成。据我所知,使用 Java DOM 实现这可能会很费力。一种捷径可能是使用不支持命名空间的 DOM 读取文档,然后添加新的默认命名空间作为属性。其他解决方案是使用 XSLT 转换更改命名空间,这在本例中似乎非常合适,因为您实际上已经通过 XSLT 转换生成输出。

使用此 XSLT 样式表将新的默认命名空间和架构位置添加到根元素。此样式表保留旧的命名空间,但将所有元素添加到新的默认命名空间(如果它们以前位于无命名空间中)。

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<!-- Template to add a default namespace to a document -->
<!-- Elements without a namespace are "moved" to default namespace -->
<!-- Elements with a namespace are copied as such -->

<!-- string for default namespace uri and schema location -->
<xsl:variable name="ns" select="'namespaceURL'"/>
<xsl:variable name="schemaLoc" select="'namespaceURL pathToMySchema.xsd'"/>

<!-- template for root element -->
<!-- adds default namespace and schema location -->
<xsl:template match="/*" priority="1">
<xsl:element name="{local-name()}" namespace="{$ns}">
<xsl:attribute name="xsi:schemaLocation"
namespace="http://www.w3.org/2001/XMLSchema-instance">
<xsl:value-of select="$schemaLoc"/>
</xsl:attribute>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>

<!--template for elements without a namespace -->
<xsl:template match="*[namespace-uri() = '']">
<xsl:element name="{local-name()}" namespace="{$ns}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>

<!--template for elements with a namespace -->
<xsl:template match="*[not(namespace-uri() = '')]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<!--template to copy attributes, text, PIs and comments -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

而不是创建变压器

Transformer trans = transfac.newTransformer();

(创建执行身份转换的样式表),创建 XSLT 输入源并将其作为参数提供给 newTransformer()

javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
Transformer trans = transFact.newTransformer(xsltSource);

其中 xsltFile 是指向该 XSLT 文件的 File 对象。

根据需要设置输出属性,并按照示例代码中的方式调用 transform()。结果应该是您想要的,但我没有在Java中对此进行测试。给定的 XSLT 文件针对一些简单的情况进行了测试,并且在本答案的末尾有一个示例输入和输出。

一些小注意事项:

  1. 在此过程中原始文档对象没有被修改。新的默认命名空间仅出现在 transform() 方法的输出中。
  2. 架构实例命名空间的命名空间前缀通常是 xsi:,而不是示例代码中的 xs:(使用 xs:在架构定义中(以及 xsd:))。
<小时/>

上面显示的 XSLT 样式表的示例输入和输出

输入:

<root>
<child>text</child>
<child attribute="attr-value"/>
<?pi-target pi-content?>
<nsx:ns-child xmlns:nsx="ns1x">
<no-ns-child>text</no-ns-child>
<!-- comment -->
<nsx:ns-child nsx:ns-attribute="nsx-attr-value">text</nsx:ns-child>
</nsx:ns-child>
<defns-child xmlns="default-ns">
<def-child attr="val">text</def-child>
<child xmlns=""/>
</defns-child>
<child>text</child>
</root>

输出:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="namespaceURL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="namespaceURL pathToMySchema.xsd">
<child>text</child>
<child attribute="attr-value"/>
<?pi-target pi-content?>
<nsx:ns-child xmlns:nsx="ns1x">
<no-ns-child>text</no-ns-child>
<!-- comment -->
<nsx:ns-child nsx:ns-attribute="nsx-attr-value">text</nsx:ns-child>
</nsx:ns-child>
<defns-child xmlns="default-ns">
<def-child attr="val">text</def-child>
<child xmlns="namespaceURL"/>
</defns-child>
<child>text</child>
</root>

关于dom - 如何通过 DOM 在 xml 文档中插入 schemalocation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4873911/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com