在出现某些值后使用 XSLT 过滤 XML 中的记录

Filter records in XML using XSLT after occurrence of certain values

我低于示例 xml,我想获取起始值 <TransactionCode>8[=39= 之间的所有 <Student> 节点]</TransactionCode> <RecordType>5</RecordType> & 结束值 <TransactionCode>9 </TransactionCode> <RecordType>5</RecordType>

样本XML

<element>
<Student>
<Name>Sam</Name>
<TransactionCode>8</TransactionCode>
<RecordType>5</RecordType>
</Student>
<Student>
<Name>bob</Name>
<TransactionCode>3</TransactionCode>
<RecordType>1</RecordType>
</Student>
<Student>
<Name>Don</Name>
<TransactionCode>9</TransactionCode>
<RecordType>5</RecordType>
</Student>
<Student>
<Name>Mike</Name>
<TransactionCode>8</TransactionCode>
<RecordType>5</RecordType>
</Student>
<Student>
<Name>Jhony</Name>
<TransactionCode>2</TransactionCode>
<RecordType>1</RecordType>
</Student>
<Student>
<Name>Alan</Name>
<TransactionCode>9</TransactionCode>
<RecordType>5</RecordType>
</Student>
 </element>

预期输出

<element>
<Student>
<Name>bob</Name>
<TransactionCode>3</TransactionCode>
<RecordType>1</RecordType>
<Student>
<Name>Jhony</Name>
<TransactionCode>2</TransactionCode>
<RecordType>1</RecordType>
</Student>
</element>

请帮助我如何使用 xslt 来完成,因为我是 xslt 的新手。

这是一个很好的 XSL 数独游戏!

创建 XPath 时,请记住多个 [] 条件在逻辑上用“and”连接,因此 //element[x][y][z] 表示所有具有 x、y 和 z 子元素的元素。

根据你的情况,使用 3 个子句。

首先,跳过 ​​8 和 9

[not(TransactionCode=8 or TransactionCode=9)]

接下来,确保 Student 有一个具有良好价值的前兄弟姐妹

[preceding-sibling::Student[TransactionCode=8][RecordType=5]]

然后,确保 Student 有一个具有良好价值的后续兄弟姐妹

[following-sibling::Student[TransactionCode=9][RecordType=5]]

最后,为确保您不匹配出现在开始和停止元素“之间”的学生,仅当开始元素多于结束元素时才输出。

全部组装在一起。

<xsl:stylesheet version='1.0' xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <!-- This would still be a TON of code in JSON!  Thanks XSL! -->
    <xsl:template match='/'>
        <element>
            <xsl:for-each select='//Student [not(TransactionCode=8 or TransactionCode=9)]
                [preceding-sibling::Student[TransactionCode=8][RecordType=5]]
                [following-sibling::Student[TransactionCode=9][RecordType=5]]
            '>
                <!--  Edit, - prevent finding students that occure after a stop element but before the next start element -->
                <xsl:variable name='startcount' select='count(preceding-sibling::Student[TransactionCode=8][RecordType=5])'/>
                <xsl:variable name='stopcount' select='count(preceding-sibling::Student[TransactionCode=9][RecordType=5])'/>
    
                <xsl:if test='$startcount &gt; $stopcount'>
                    <xsl:copy-of select='.'/>
                </xsl:if>
            </xsl:for-each>
        </element>
    </xsl:template>
    </xsl:stylesheet>