0

我是 xslt 的新手。我正在尝试将 XML 从一种模式转换为另一种模式。我想在转换后“摆脱”旧的命名空间。如果转换本身需要旧模式,如何在转换后擦除旧模式。本质上,我想http://positionskillmanagementservice.webservices.com离开并完全被替换http://newschema(在我重命名节点之后)。我可以通过 Dimitre Novatchev 的方法来做我想做的大部分事情:使用 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>

我正在使用这个工具检查工作。

4

2 回答 2

2

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

于 2013-04-23T07:43:50.083 回答
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>

笔记

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

    <positionSkillResponse xmlns="http://newschema">
        <return>1</return>
        <return>9</return>
    </positionSkillResponse>
    
于 2013-04-23T03:50:30.580 回答