用xslt摆脱旧命名空间

时间:2013-04-23 03:25:40

标签: xml xslt

我是xslt的新手。我试图将XML从一个模式转换为另一个模式。我希望在转换后“摆脱”旧的命名空间。如果转换本身需要它,如何在转换后擦除旧模式。基本上,我希望http://positionskillmanagementservice.webservices.com消失并完全被http://newschema替换(在我重命名节点之后)。我可以通过Dimitre Novatchev的方法完成我想要的大部分工作:change the namespace of an element with xslt

这是XML:

<ns:positionSkillResponse xmlns:ns="http://positionskillmanagementservice.webservices.com">
<ns:return>1</ns:return>
<ns:return>9</ns:return>
</ns:positionSkillResponse>

这是xslt:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://positionskillmanagementservice.webservices.com"
  version="1.0">

  <xsl:output method="xml" />

  <xsl:template match="ns:return">
    <parameter>
      <xsl:apply-templates select="@*|node()"/>
    </parameter>
  </xsl:template>

   <xsl:template match="ns:position">
    <parameter>
      <xsl:apply-templates select="@*|node()"/>
    </parameter>
  </xsl:template>

  <xsl:template match="ns:positionSkillResponse">
    <positionSkillRequest >
      <xsl:apply-templates select="@*|node()"/>
    </positionSkillRequest >
  </xsl:template>

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

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

我正在使用this tool检查工作。

2 个答案:

答案 0 :(得分:2)

Tomalak向您展示了编写转换的更好方法,但并没有真正回答您的直接问题。在样式表中使用文字结果元素时,例如<a>...</a>,它们将与样式表中该元素的范围内的所有名称空间一起复制到输出中,但有一些例外。其中一个例外是,如果名称空间列在exclude-result-prefixes元素中,则省略名称空间,该元素通常与名称空间声明一起放在xsl:stylesheet元素上。因此,如果你没有按照Tomalak的建议重构样式表,你可以通过在xsl:stylesheet元素中添加exclude-result-prefixes =“ns”来删除命名空间。

答案 1 :(得分:1)

你的尝试太具体了。试试这个更通用的一个:

<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns_old="http://positionskillmanagementservice.webservices.com"
>    
    <xsl:output method="xml" />

    <!-- matches any node not handled elsewhere -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>    

    <!-- matches elements in the old namespace, re-creates them in the new -->
    <xsl:template match="ns_old:*">
        <xsl:element name="ns:{local-name()}" namespace="http://newschema">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <!-- if you don't have namespaced attributes you won't need this template -->
    <xsl:template match="@ns_old:*">
        <xsl:attribute name="ns:{local-name()}" namespace="http://newschema">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

提供:

<ns:positionSkillResponse xmlns:ns="http://newschema">
    <ns:return>1</ns:return>
    <ns:return>9</ns:return>
</ns:positionSkillResponse>

注释

  • 您不需要在XSLT中声明xmlns:ns="http://newschema",因为您的输入文档中实际上没有来自该命名空间的节点。
  • 这也意味着您可以将旧命名空间声明为xmlns:ns="http://positionskillmanagementservice.webservices.com",并将其用作<xsl:template match="ns:*">。它与XSL处理器完全相同,但如果使用ns_old这样的不同前缀,它可能会让人类读者感到困惑。
  • 您可以任意选择输出前缀(<xsl:element name="ns:{local-name()}" ...)。这与XSLT中声明的命名空间无关。根本不使用前缀会导致文档具有默认命名空间:

    <positionSkillResponse xmlns="http://newschema">
        <return>1</return>
        <return>9</return>
    </positionSkillResponse>