我一直在寻找这种特殊情况,但没有找到。我有这个XML,除了这三个元素外还有其他元素,但是它们是不相关的。相关元素具有两个附加的名称空间。我要删除xmlns:two,因此在输出中仅出现第一个xmlns。
<?xml version="1.0" encoding="UTF-8"?>
<Header>
<one:id xmlns:one="http://x.com/xsd/so"
xmlns:two="http://x.com/xsd/woa.xsd">555</one:id>
<one:protocolVersion xmlns:one="http://x.com/xsd/so"
xmlns:two="http://x.com/xsd/woa.xsd">2.0</one:protocolVersion>
<one:userId xmlns:one="http://x.com/xsd/so"
xmlns:two="http://x.com/xsd/woa.xsd">12345</one:userId>
</Header>
现在我想要的是删除xmlns:two
<?xml version="1.0" encoding="UTF-8"?>
<Header>
<one:id xmlns:one="http://x.com/xsd/so">555</one:id>
<one:protocolVersion xmlns:one="http://x.com/xsd/so">2.0</one:protocolVersion>
<one:userId xmlns:one="http://x.com/xsd/so">12345</one:userId>
</Header>
我已经尝试过类似的方法,但是它删除了错误的名称空间。它将删除前缀相同的名称空间。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:two="http://x.com/xsd/woa.xsd"
xmlns:one="http://x.com/xsd/so">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="one:id">
<xsl:element name="{local-name()}">
<xsl:copy-of select="namespace::*[not(. = namespace-uri(..))]"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
您想要的xsl:copy-of
表达式是这样,仅复制与当前元素匹配的名称空间
<xsl:copy-of select="namespace::*[. = namespace-uri(..)]"/>
此外,您应该使用name()
而不是local-name()
创建元素,否则,鉴于您没有默认名称空间,因此您应该在没有名称空间的情况下创建元素。
但是,当您创建一个具有在XSLT中声明的前缀的新元素时,我认为您根本不需要复制名称空间。
尝试使用此XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:one="http://x.com/xsd/so">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="one:*">
<xsl:element name="{name()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
注意,如果您可以使用XSLT 2.0,也可以这样做。...
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:one="http://x.com/xsd/so">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="one:*">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
有很多因素阻止了它创建您描述的结果:
在这里,您只复制元素不使用的名称空间,而不是它所使用的名称空间:
<xsl:copy-of select="namespace::*[not(. = namespace-uri(..))]"/>
这里您要在null命名空间(没有命名空间)中创建一个元素:
<xsl:element name="{local-name()}">
您已经在XSLT样式表的根元素上声明了one
和two
命名空间,这意味着它们将包含在输出文档的根元素中。
为了获得您描述的结果,可以使用以下方法:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="one:*" xmlns:one="http://x.com/xsd/so" >
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
或者您可以使用与名称空间无关的更通用的方法:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这两种方法都能产生您想要的输出。