2013-04-23 102 views
0

我是xslt的新手。我试图将XML从一个模式转换为另一个模式。我想在转换后“摆脱”旧的命名空间。如果我需要它进行转换,我如何在转换后擦除旧的模式。本质上,我想http://positionskillmanagementservice.webservices.com消失,完全由http://newschema(我重新命名节点后)替换。我能够通过从Dimitre Novatchev的方法来执行大部分的我想要的东西:change the namespace of an element with xslt用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

回答

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> 
    
2

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