我有一个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>
我希望获得属性类型Screening
和PEMP
中唯一一个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
的筛选元素
此外,它还应列出Screening
和PEMP
以外的其他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>
答案 0 :(得分:1)
由于您使用的是XSLT 2.0,因此可以声明排序顺序并拆分值
<xsl:param name="sortOrder" select="'Fail,Review,Pass'" />
<xsl:variable name="valSequence" select="tokenize($sortOrder, ',')"/>
使用ResultStatus
元素的声明顺序对Screening
执行排序,@type
元素的值为FEMP
和PEMP
,并获取第一个元素输出
<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>