使用xslt

时间:2018-06-07 06:34:35

标签: xml xslt

我有一个XML,如下所示

<BackgroundReports>
    <BackgroundReportPackage>
        <Screenings>
            <Screening type="PEMP">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Review</ResultStatus>
                </ScreeningStatus>
            </Screening>
            <Screening type="PEMP">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Review</ResultStatus>
                </ScreeningStatus>
            </Screening>
            <Screening type="FEMP">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Fail</ResultStatus>
                </ScreeningStatus>
            </Screening>
            <Screening type="PEMP">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Pass</ResultStatus>
                </ScreeningStatus>
            </Screening>
            <Screening type="TEST">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Review</ResultStatus>
                </ScreeningStatus>
            </Screening>
        </Screenings>
    </BackgroundReportPackage>
</BackgroundReports>

我希望获得属性类型ScreeningPEMP中唯一一个FEMP元素,具体取决于<ResultStatus>值中的优先级值。

如果XML的结果状态为<ResultStatus>Fail</ResultStatus>,那么只获取该屏蔽元素<ResultStatus>Fail</ResultStatus>

Ouuput将

<BackgroundReports>
    <BackgroundReportPackage>
        <Screenings>
            <Screening type="FEMP">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Fail</ResultStatus>
                </ScreeningStatus>
            </Screening>
            <Screening type="TEST">
                <ScreeningStatus>
                    <OrderStatus>Completed</OrderStatus>
                    <ResultStatus>Fail</ResultStatus>
                </ScreeningStatus>
            </Screening>
        </Screenings>
    </BackgroundReportPackage>
</BackgroundReports>

它从原始XML中删除了3个FEMP / PEMP筛选元素。

第二优先级为Review(如果不存在失败) - <ResultStatus>Review</ResultStatus>但如果多个/所有具有Review

的筛选元素,则只获得一个元素

第三个是Pass(如果不存在Review and Fail),但如果多个/所有具有Pass的筛选元素

,则只获得一个元素

此外,它还应列出ScreeningPEMP以外的其他FEMP元素

这是我到目前为止工作的xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://www.cpscreen.com/schemas"
    xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes"
    xmlns:my="http://www.fadv.com" exclude-result-prefixes="my fn xs xdt">
    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />

   <xsl:template match="node()|@*">
        <!-- Copy the current node -->
        <xsl:copy>
            <!-- Including any attributes it has and any child nodes -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/ns0:BackgroundReports/ns0:BackgroundReportPackage/ns0:Screenings">
        <test><xsl:value-of select="count(ns0:Screening)"/></test>
        <xsl:variable name="eduResultStatus"/>
        <xsl:for-each select="ns0:Screening[@type='PEMP' or @type='FEMP']">
            <!-- Yet to work here -->
        </xsl:for-each>

        <xsl:for-each select="ns0:Screening[@type != 'PEMP' and @type != 'FEMP']">
            <xsl:copy>
                <!-- Including any attributes it has and any child nodes -->
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

由于您使用的是XSLT 2.0,因此可以声明排序顺序并拆分值

<xsl:param name="sortOrder" select="'Fail,Review,Pass'" />
<xsl:variable name="valSequence" select="tokenize($sortOrder, ',')"/>

使用ResultStatus元素的声明顺序对Screening执行排序,@type元素的值为FEMPPEMP,并获取第一个元素输出

<xsl:for-each select="Screening[@type = 'FEMP' or @type = 'PEMP']">
    <xsl:sort select="index-of($valSequence, ScreeningStatus/ResultStatus)" />
    <!-- Get 1st element after sorting -->
    <xsl:if test="position() = 1">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:if>
</xsl:for-each>

对于其余节点,按原样应用

<xsl:apply-templates select="Screening[not(@type = 'FEMP' or @type = 'PEMP')]" />

完整的XSLT如下

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

    <xsl:param name="sortOrder" select="'Fail,Review,Pass'" />
    <xsl:variable name="valSequence" select="tokenize($sortOrder, ',')"/>

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

    <xsl:template match="Screenings">
        <xsl:copy>
            <xsl:for-each select="Screening[@type = 'FEMP' or @type = 'PEMP']">
                <xsl:sort select="index-of($valSequence, ScreeningStatus/ResultStatus)" />
                <!-- Get 1st element after sorting -->
                <xsl:if test="position() = 1">
                    <xsl:copy>
                        <xsl:apply-templates select="@* | node()" />
                    </xsl:copy>
                </xsl:if>
            </xsl:for-each>
            <xsl:apply-templates select="Screening[not(@type = 'FEMP' or @type = 'PEMP')]" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输出

<BackgroundReports>
   <BackgroundReportPackage>
      <Screenings>
         <Screening type="FEMP">
            <ScreeningStatus>
               <OrderStatus>Completed</OrderStatus>
               <ResultStatus>Fail</ResultStatus>
            </ScreeningStatus>
         </Screening>
         <Screening type="TEST">
            <ScreeningStatus>
               <OrderStatus>Completed</OrderStatus>
               <ResultStatus>Review</ResultStatus>
            </ScreeningStatus>
         </Screening>
      </Screenings>
   </BackgroundReportPackage>
</BackgroundReports>