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

时间:2019-01-04 13:28:21

标签: xslt 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>

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

2 个答案:

答案 0 :(得分:0)

您尚未在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的模板,就像您自己不希望这些元素一样,您确实需要处理子节点。

答案 1 :(得分:0)

您需要将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