XSLT 1.0,复制除某些子节点之外的所有子节点



我正在尝试将所有子节点复制到特定节点,除了少数几个。一直无法让它工作?有什么指示我做错了什么吗?

使用此 XML:

<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/">
    <ns0:Header>
        <wsse:Sec xmlns:wsse="http://docs.x.org/wsse/"> 
            <saml:Ass xmlns:saml="http://docs.x.org/saml/">
                <ds:Sign xmlns:ds="http://docs.x.org/ds/">
                    <ds:SignVal>SignatureValue</ds:SignVal>
                </ds:Sign>
                <saml:subj>SubjectValue</saml:subj>
            </saml:Ass>
        </wsse:Sec>
        <To>http://localhost:8080/Test/</To>
        <Action>SendTest</Action>
    </ns0:Header>
    <ns0:Body>...</ns0:Body>
</ns0:Envelope>

想要的结果是只获取 Sec 标签和所有子项:

<wsse:Sec xmlns:wsse="http://docs.x.org/wsse/"> 
   <saml:Ass xmlns:saml="http://docs.x.org/saml/">
      <ds:Sign xmlns:ds="http://docs.x.org/ds/">
         <ds:SignVal>SignatureValue</ds:SignVal>
      </ds:Sign>
      <saml:subj>SubjectValue</saml:subj>
   </saml:Ass>
</wsse:Sec>

我已经尝试了许多XSL,包括:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    <xsl:template match="Header">
        <xsl:copy-of select="*"/>
    </xsl:template>
    <!-- Exclude these -->
    <xsl:template match="To" />
    <xsl:template match="Action" />
</xsl:stylesheet>

结果是我得到了值但没有标签...

您尚未考虑 XSLT 中的命名空间。在 XML 中,Header 位于命名空间http://schemas.xmlsoap.org/soap/envelope/ 中,但 XSLT 尝试匹配没有命名空间中的Header

您需要在 XSLT 中声明命名空间,并在模板匹配中使用它们

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
                              xmlns:wsse="http://docs.x.org/wsse/">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    <xsl:template match="ns0:Header">
        <xsl:copy-of select="wsse:Sec"/>
    </xsl:template>
    <xsl:template match="ns0:Body" />
</xsl:stylesheet>

请注意,此 XSLT 不需要与"To"和"Action"匹配的模板,因为使用此方法显式复制wsse:Sec。但是,您确实需要模板以确保不会选取ns0:Body中的任何测试。

另一种方法是使用标识模板,然后您将拥有要排除ToAction(和Body)的模板

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
                              xmlns:wsse="http://docs.x.org/wsse/">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="ns0:Envelope|ns0:Header">
        <xsl:apply-templates />
    </xsl:template>
    <!-- Exclude these -->
    <xsl:template match="ns0:Body|To|Action" />
</xsl:stylesheet>

请注意,有一个ns0:Envelopens0:Header匹配的模板,因为尽管您不需要这些元素本身,但确实需要处理子节点。

您需要

将 XSLT 2 或 3 与

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:wsse="http://docs.x.org/wsse/"
    exclude-result-prefixes="#all"
    version="3.0">
  <xsl:template match="/">
      <xsl:copy-of select="//wsse:Sec" copy-namespaces="no"/>
  </xsl:template>
</xsl:stylesheet>

要使用简单的复制指令获取发布的结果:https://xsltfiddle.liberty-development.net/bnnZVw

在 XSLT 1 中,副本将始终复制作用域内命名空间xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"因此,要将其从结果中删除,您需要通过某种转换来运行代码,剥离作用域内的命名空间(元素本身除外):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wsse="http://docs.x.org/wsse/"
    exclude-result-prefixes="wsse"
    version="1.0">
  <xsl:template match="@*">
      <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
          <xsl:value-of select="."/>
      </xsl:attribute>
  </xsl:template>
  <xsl:template match="*">
      <xsl:element name="{name()}" namespace="{namespace-uri()}">
          <xsl:apply-templates select="@* | node()"/>
      </xsl:element>
  </xsl:template>
  <xsl:template match="/">
      <xsl:apply-templates select="//wsse:Sec"/>
  </xsl:template>
</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bnnZVw/1

相关内容

  • 没有找到相关文章

最新更新