使用 XSL 删除命名空间并提取 XML 文件的子集
当我的输入 Xml 为:
<country>
<state>
<city>
<name>DELHI</name>
</city>
</state>
</country>
对于如下所需的输出:
<city>
<name>DELHI</name>
</city
以下 xsl 工作正常:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:copy-of select="//city">
</xsl:copy-of>
</xsl:template>
</xsl:stylesheet>
但相同的 XSL 不适用于上述输入 XML,如果添加了名称空间: 如下所示:
<country xmlns="http://india.com/states" version="1.0">
<state>
<city>
<name>DELHI</name>
</city>
</state>
</country>
我希望名称空间与要复制的城市元素一起被删除。
任何帮助将不胜感激。 谢谢
When my Input Xml as :
<country>
<state>
<city>
<name>DELHI</name>
</city>
</state>
</country>
For required output as below:
<city>
<name>DELHI</name>
</city
The following xsl is working fine :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:copy-of select="//city">
</xsl:copy-of>
</xsl:template>
</xsl:stylesheet>
BUT THE SAME XSL IS NOT WORKING FOR THE ABOVE INPUT XML , IF NAME SPACE IS ADDED :
Like Below :
<country xmlns="http://india.com/states" version="1.0">
<state>
<city>
<name>DELHI</name>
</city>
</state>
</country>
I want the name space to be removed along with the city element to be copied .
Any help would be appreciated .
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是有关 XPath、XML 和 XSLT 的最多常见问题解答。搜索“默认命名空间和 XPath 表达式”。
解决方案:
当此转换应用于提供的 XML 文档时:
想要的结果生成:
解释:
在 XPath 中,无前缀的元素名称始终被认为位于“无命名空间”中。但是,所提供的 XML 文档中的每个元素名称都位于非空命名空间中(默认命名空间
"http://india.com/states"
)。因此,//city
不选择任何节点(因为 XML 文档中没有任何元素不是命名空间),而//x:city
其中x:
绑定到命名空间"http://india.com/states"
选择所有城市元素(位于命名空间"http://india.com/states "
).在此转换中有两个模板。第一个模板匹配任何元素并重新创建它,但在无命名空间中。它还复制所有属性,然后将模板应用于该元素的子节点。
对于不是
city
元素的祖先或本身不是city
元素的所有元素,第二个模板会覆盖第一个模板。这里的操作是在所有子节点上应用模板。更新:OP修改了询问为什么在处理新的、修改的XML文档的结果中存在不需要的文本的问题:
为了不生成文本“ MUMBAI”,上面的转换需要稍微修改一下——忽略(而不是复制)任何没有
x:city
祖先的文本节点。为此,我们添加以下一行空模板:整个转换现在变为:
结果仍然是想要的正确结果:
This is the most FAQ on XPath, XML and XSLT. Search for "default namespace and XPath expressions".
As for a solution:
when this transformation is applied on the provided XML document:
the wanted result is produced:
Explanation:
In XPath an unprefixed element-name is always considerd to be in "no namespace". However, every element name in the provided XML document is in a non-empty namespace (the default namespace
"http://india.com/states"
). Therefore,//city
selects no node (as there is no element in the XML document that is no namespace), while//x:city
wherex:
is bound to the namespace"http://india.com/states"
selects all city elements (that are in the namespace"http://india.com/states"
).In this transformation there are two templates. The first template matches any element and re-creates it, but in no-namespace. It also copies all atributes and then applies templates to the children-nodes of this element.
The second template overrides the first for all elements that are not ancestors of a
city
element or not themselves acity
element. The action here is to apply templates on all children nodes.UPDATE: The OP has modified the question asking why there is non-wanted text in the result of processing a new, modified XML document:
In order not to produce the text "MUMBAI", the transformation above needs to be slightly modified -- to ignore (not copy) any text node that hasn't an
x:city
ancestor. For this purpose, we add the following one-line, empty template:The whole transformation now becomes:
and the result is still the wanted, correct one:
您可以使用以下模板获得所需的输出:
或
在它提供的新输入上使用 Microsoft (R) XSLT Processor Version 4.0 进行测试:
You can get the wanted output by using a template like:
or
Tested with Microsoft (R) XSLT Processor Version 4.0 on your new input it gives: