当我的输入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>
我希望删除名称空间以及要复制的城市元素。
任何帮助将不胜感激。 感谢
答案 0 :(得分:3)
这是XPath,XML和XSLT上最常见的FAQ。搜索“默认命名空间和XPath表达式”。
关于解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://india.com/states">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[not(ancestor-or-self::x:city)]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<country xmlns="http://india.com/states" version="1.0">
<state>
<city>
<name>DELHI</name>
</city>
</state>
</country>
生成了想要的结果:
<city>
<name>DELHI</name>
</city>
<强>解释强>:
在XPath中,一个没有前缀的元素名称总是被认为是“无命名空间”。但是,提供的XML文档中的每个元素名称都在非空名称空间(默认名称空间"http://india.com/states"
)中。因此,//city
不选择任何节点(因为XML文档中没有没有名称空间的元素),而//x:city
其中x:
绑定到名称空间"http://india.com/states"
选择所有城市元素(位于名称空间"http://india.com/states"
)。
在此转换中,有两个模板。第一个模板匹配任何元素并重新创建它,但是在无命名空间中。它还复制所有属性,然后将模板应用于此元素的子节点。
第二个模板会覆盖不是city
元素祖先的所有元素的第一个模板,或者它们本身不是city
元素。此处的操作是在所有子节点上应用模板。
更新:OP修改了一个问题,询问为什么处理新的修改后的XML文档的结果中存在非通缉文本:
<country xmlns="http://india.com/states" version="1.0">
<state>
<city>
<name>DELHI</name>
</city>
</state>
<state2>
<city2>
<name2>MUMBAI</name2>
</city2>
</state2>
</country>
为了不生成文本“MUMBAI”,需要稍微修改上面的转换 - 忽略(不复制)任何没有x:city
的文本节点祖先。为此,我们添加以下单行空模板:
<xsl:template match="text()[not(ancestor::x:city)]"/>
整个转型现在变为:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://india.com/states">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[not(ancestor-or-self::x:city)]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[not(ancestor::x:city)]"/>
</xsl:stylesheet>
,结果仍然是想要的,正确的:
<city>
<name>DELHI</name>
</city>
答案 1 :(得分:0)
您可以使用以下模板获取所需的输出:
<xsl:template match="*[not(ancestor-or-self::x:*[starts-with(name(),'city')])]">
<xsl:apply-templates/>
</xsl:template>
或
<xsl:template match="/">
<xsl:apply-templates select="//x:*[starts-with(name(),'city')]"/>
</xsl:template>
在新输入上使用 Microsoft(R)XSLT处理器版本4.0 进行测试,它提供了:
<city>
<name>DELHI</name>
</city>
<city2>
<name2>MUMBAI</name2>
</city2>