我用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);
谢谢你的时间,
卡斯滕
解决方法@H_403_18@
在XML数据模型中,命名空间节点实际上不是从父元素读取的,但每个元素都有自己的命名空间节点.因此,简单地向根元素添加新的默认命名空间不起作用,但会生成这样的文档
<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();
(创建和执行identy转换的样式表),创建一个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文件针对一些简单的案例进行了测试,并且在此答案的末尾有一个示例输入和输出.
一些小调:
>在此过程中不会修改原始文档对象.新的默认命名空间仅出现在transform()方法的输出中.
> schema-instance命名空间的名称空间前缀通常是xsi:,而不是xs:在示例代码中(xs:用于模式定义(以及xsd :)).
输入:
<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>
<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();
(创建和执行identy转换的样式表),创建一个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文件针对一些简单的案例进行了测试,并且在此答案的末尾有一个示例输入和输出.
一些小调:
>在此过程中不会修改原始文档对象.新的默认命名空间仅出现在transform()方法的输出中.
> schema-instance命名空间的名称空间前缀通常是xsi:,而不是xs:在示例代码中(xs:用于模式定义(以及xsd :)).
输入:
<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>