提问人:User_Earth_005 提问时间:6/8/2023 最后编辑:User_Earth_005 更新时间:6/8/2023 访问量:40
XSLT 中的特定方案
Specific Scenario in XSLT
问:
我删除了上一篇文章以使其更清楚。
输入 XML
<Org>
<Name>OrgName</Name>
<Type>OrgType</Type>
<Customer>OrgCust</Customer>
<Product>
<ProductData>
<ID>ID1</ID>
<Name>Prod1</Name>
<Grade>Grade1</Grade>
<Number>13</Number>
</ProductData>
<ProductData>
<ID>ID2</ID>
<Name>Prod2</Name>
<Grade>Grade2</Grade>
<Number>12</Number>
</ProductData>
<ProductData>
<ID>ID3</ID>
<Name>Prod3</Name>
<Grade>Grade3</Grade>
<Number>10</Number>
</ProductData>
</Product>
<Market>TestMarket</Market>
<Quality>Tested</Quality>
<Score>70</Score>
</Org>
要求是根据大于 10 的 <Number> 标记值将名为 <Status>Done</Status> 的节点添加到组 Product/ProductData。
如果 XML 中存在 ID3 且 <Number> 大于 10。<Status>Done</Status> 标记应仅添加到 ID3 中。
如果 ID3 无效(<Number>不大于 10)且 ID1 和 ID2 都存在于 XML 中且有效(<Number>大于 10),则在 ID2 中添加 <Status>Done</Status> 标记。
否则,如果 ID2 和 ID3 无效(<Number>大于 10)且 ID1 有效(<Number>大于 10),则将 <Status>Done</Status> 标记添加到 ID1。
ID1、ID2 和 ID3 的出现不是固定的。
下面是我的XSLT。在这里,我发现这很难实现第 2 点,即 ID1 和 ID2 都有效。我需要一个全局变量,如果一个验证匹配,请设置该变量的值。然后,我将使用 in 循环检查变量的值并跳过所有其他验证。我尝试了很多方法,但无法弄清楚这一点。我浏览了很多帖子,但没有提到在 for-each 中使用标志或在条件满足时打破循环。任何关于这方面的指导都将非常有帮助。
<xsl:template match="Org/Product">
<xsl:for-each select="ProductData">
<xsl:choose>
<xsl:when test="ID ='ID1' and Number>10">
<Status>Done</Status>
</xsl:when>
<xsl:when test="ID ='ID2' and Number>10">
<Status>Done</Status>
</xsl:when>
<xsl:when test="ID ='ID3' and Number>10">
<Status>Done</Status>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
我正在寻找的输出如下
<Org>
<Name>OrgName</Name>
<Type>OrgType</Type>
<Customer>OrgCust</Customer>
<Product>
<ProductData>
<ID>ID1</ID>
<Name>Prod1</Name>
<Grade>Grade1</Grade>
<Number>13</Number>
</ProductData>
<ProductData>
<ID>ID2</ID>
<Name>Prod2</Name>
<Grade>Grade2</Grade>
<Number>12</Number>
<Status>Done</Status>
</ProductData>
<ProductData>
<ID>ID3</ID>
<Name>Prod3</Name>
<Grade>Grade3</Grade>
<Number>10</Number>
</ProductData>
</Product>
<Market>TestMarket</Market>
<Quality>Tested</Quality>
<Score>70</Score>
</Org>
XSLT 的版本为 1.0。请帮忙。
答:
0赞
michael.hor257k
6/8/2023
#1
尝试类似的东西:
XSLT 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="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="id">
<xsl:variable name="product" select="/Org/Product/ProductData" />
<xsl:choose>
<xsl:when test="$product[ID='ID3']/Number > 10">ID3</xsl:when>
<xsl:when test="$product[ID='ID2']/Number > 10">ID2</xsl:when>
<xsl:when test="$product[ID='ID1']/Number > 10">ID1</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:template match="ProductData">
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="ID = $id">
<Status>Done</Status>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果我们可以确定输入中列出的顺序(或者至少如果它们可以按所需的顺序按某些属性排序),我们可以更简单地定义变量 - 例如:ProductData
id
<xsl:variable name="id" select="/Org/Product/ProductData[Number > 10][last()]/ID" />
评论
0赞
User_Earth_005
6/8/2023
明白了。解决方案正在发挥作用。非常感谢。。。。我正在尝试使用 for-each,但看起来这是不可能的。模板匹配是正确的方法。再次感谢你。
0赞
michael.hor257k
6/8/2023
请记住,这不是一个“循环”。xsl:for-each
0赞
User_Earth_005
6/8/2023
理解。谢谢。
评论
ProductData
ID3
<Number>13</Number>
<Status>Done</Status>
ProductData
ID2