Xslt按顺序排除元素

时间:2014-01-02 17:05:50

标签: xml xslt

我有这个XML文件:

<ID>
    <T1>
        <T2>XXXXX</T2>
        <T2>XXXXX</T2>
    </T1>
    <T3>
        <T4>
        <TxId>AAAXXXXXXXXXXX</TxId>
        </T4>       
        <T4>
        <TxId>BBBXXXXXXXXXXX</TxId>
        </T4>    
        <T4>
        <TxId>BBXXXXXXXXXXX</TxId>
        </T4>
    </T3>
    <T5>
        <T6>
        <Mod>gfh</Mod>
        </T6>
        <T6>
        <Mod>fhg</Mod>
        </T6>
        <T6>
        <Mod>fgh</Mod>
        </T6>
    </T5>
</ID>

当TxId = AAA的3个第一个字符时,我需要排除T4元素 如果我排除第一个T4我必须排除第一个T6,如果第6个T4元素是excluse我需要排除第6个T6元素。

我试过了:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="T4[starts-with(TxId,'AAA')]">  
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="T4"/> 

</xsl:stylesheet>

但我不知道如何加入T4 / T6排除 谢谢

3 个答案:

答案 0 :(得分:4)

怎么样:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="t4" match="T4" use="count(preceding-sibling::T4)" />

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

<xsl:template match="T4[starts-with(TxId,'AAA')]"/>  
<xsl:template match="T6[starts-with(key('t4', count(preceding-sibling::T6))/TxId,'AAA')]"/> 

</xsl:stylesheet>

答案 1 :(得分:1)

如果您使用

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

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

<xsl:template match="T4[starts-with(TxId, 'AAA')] | 
                     T6[../../T3/T4[starts-with(TxId, 'AAA')] and count(preceding-sibling::T6) = count(../../T3/T4[starts-with(TxId, 'AAA')]/preceding-sibling::T4)]"/>

</xsl:stylesheet>

然后只要只有一个T3T5它就可以运作。

答案 2 :(得分:1)

通过基于身份模板的转换,您已经有了一个良好的开端。我在这里要做的是创建一个匹配所有T6元素的模板,然后将该代理委托给您想要排除的项目的身份模板

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<!-- exclude T4 that start with AAA -->
<xsl:template match="T4[starts-with(TxId, 'AAA')]" />

<xsl:template match="T6">
  <!-- save our position in the parent's list of child nodes - thanks to the
       strip-space this will match the position of the corresponding T4 within
       its parent -->
  <xsl:variable name="mypos" select="position()" />

  <xsl:if test="starts-with(../../T3/T4[$mypos]/TxId, 'AAA')">
    <xsl:call-template name="ident" />
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

如果这些位置不一定精确排列(请记住position()apply-templates select表达式导致此模板触发的内容非常敏感,那么如果T5有任何意义,那么它将会中断属性或除T6元素之外的任何其他孩子)然后说

可能更安全
<xsl:variable name="mypos" select="count(preceding-sibling::T6) + 1" />