使用xslt中的条件复制不带命名空间

时间:2016-04-20 05:46:51

标签: xml xslt namespaces xslt-1.0

我正在使用此模板进行没有命名空间的复制:

<xsl:template match="*" mode="copy-no-namespaces">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
    </xsl:element>
</xsl:template>

<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
    <xsl:copy/>
</xsl:template>
这是有效的。但是我希望它在没有特定名称空间而不是所有名称空间的情例如,我想忽略一些名称空间,如http://test.comhttp://test2.com,副本应仅删除这些名称空间,而不是所有名称空间。

示例:

<xs:schema xmlns:xxx="http://include.com" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:zzz="http:test.com" >
   <zzz:element>
   </zzz:element>

   <xxx:complexType>
   </xxx:complexType>
</xs:schema>

应删除此zzz命名空间,但保留xxx zzz 匹配http://test.com,因此输出将为

<xs:schema xmlns:xxx="http://include.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <element>
   </element>

   <xxx:complexType>
   </xxx:complexType>
</xs:schema>

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

我认为你可能会在将元素移动到不同(或没有)命名空间和复制命名空间(即命名空间声明)之间混淆。您应该只需要将zzz:前缀元素移动到无命名空间 - 并且无需关心输出是否包含现在冗余的命名空间声明:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http:test.com"
exclude-result-prefixes="ns1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="ns1:*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

P.S。如果您愿意,可以在不声明任何前缀的情况下执行相同的操作:

<xsl:template match="*[namespace-uri()='http:test.com']">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

答案 1 :(得分:0)

使用优先级较高的模板将元素保留在给定的命名空间中:

<xsl:template match="*"
              mode="copy-no-namespaces">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates select="node() | @*" mode="copy-no-namespaces"/>
  </xsl:element>
</xsl:template>

<xsl:template match="xxx:*" xmlns:xxx="http://include.com"
              mode="copy-no-namespaces">
  <xsl:element name="{name()}" namespace="{namespace-uri()}">
    <xsl:apply-templates select="node() | @*" mode="copy-no-namespaces"/>
  </xsl:element>
</xsl:template>

<xsl:template match="node() | @*"
              mode="copy-no-namespaces"
              priority="-10">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*"/>
  </xsl:copy>
</xsl:template>

第一个模板从元素中剥离命名空间,第二个模板在元素中保留命名空间http://include.com,最后一个模板保留其他所有内容。

第二个模板可以使用xsl:copy而不是xsl:element,但这会复制范围内的所有命名空间,并且您最终会使用冗余的命名空间声明。