带中断的 Xslt 嵌套 For 循环

发布于 2025-01-08 08:46:48 字数 1429 浏览 0 评论 0原文

总之,

我是 XSLT 的新手,面临着一个典型的问题。下面是问题详细信息

根据下面的数据,我仅当 ItemA/ANum 元素属于 AName BBC 而不是 ItemB/tempBNum 的一部分时才需要显示 ItemA/ANum 元素,

因此以下数据的所需结果应该是 0214,BBC,因为它是ItemA,也是一个BBC,没有出现在ItemB中。

<myData>
<ItemA>
    <ANum>0213</ANum>
    <AName>OOC</AName>
</ItemA>
<ItemA>
    <ANum>0031</ANum>
    <AName>BBC</AName>
</ItemA>
<ItemA>
    <ANum>0214</ANum>
    <AName>BBC</AName>
</ItemA>
<ItemA>
    <ANum>0044</ANum>
    <AName>BBC</AName>
</ItemA>

<ItemB>
    <tempBNum>0031</tempBNum>
</ItemB>
<ItemB>
    <tempBNum>0044</tempBNum>
</ItemB>
</myData>

为此,我尝试放入嵌套 For 循环的逻辑,唯一的问题是当 ItemAObj/ANum = tempBNum 时嵌套循环应该中断,但它不会中断并产生重复的结果。

  <xsl:for-each select="myData/ItemA">
    <xsl:variable name="ItemAObj" select="." />
    Num = <xsl:value-of select="$ItemAObj/ANum"/>
    <xsl:for-each select="/myData/ItemB">
    <xsl:choose>
        <xsl:when test="$ItemAObj/ANum!=tempBNum and $ItemAObj/AName='BBC'"> <xsl:value-of select="tempBNum"/>
        <xsl:text> </xsl:text>
    </xsl:when>
        </xsl:choose>
        </xsl:for-each>
  </xsl:for-each>

对此的任何帮助将不胜感激。

All,

I'm new to XSLT and facing a typical problem. Below is the problem details

Based on the data below, i needed to show ItemA/ANum element only when its of AName BBC and not part of ItemB/tempBNum

So desired result for the below data should be 0214,BBC, since its part of the ItemA, also is a BBC is does not appear in ItemB.

<myData>
<ItemA>
    <ANum>0213</ANum>
    <AName>OOC</AName>
</ItemA>
<ItemA>
    <ANum>0031</ANum>
    <AName>BBC</AName>
</ItemA>
<ItemA>
    <ANum>0214</ANum>
    <AName>BBC</AName>
</ItemA>
<ItemA>
    <ANum>0044</ANum>
    <AName>BBC</AName>
</ItemA>

<ItemB>
    <tempBNum>0031</tempBNum>
</ItemB>
<ItemB>
    <tempBNum>0044</tempBNum>
</ItemB>
</myData>

For this end, I tried putting in a logic of having Nested For Loops, only problem being nested loop should break when ItemAObj/ANum = tempBNum, but its not breaking and producing duplicate results.

  <xsl:for-each select="myData/ItemA">
    <xsl:variable name="ItemAObj" select="." />
    Num = <xsl:value-of select="$ItemAObj/ANum"/>
    <xsl:for-each select="/myData/ItemB">
    <xsl:choose>
        <xsl:when test="$ItemAObj/ANum!=tempBNum and $ItemAObj/AName='BBC'"> <xsl:value-of select="tempBNum"/>
        <xsl:text> </xsl:text>
    </xsl:when>
        </xsl:choose>
        </xsl:for-each>
  </xsl:for-each>

Any help on this will be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情域 2025-01-15 08:46:48

您不需要使用任何 xsl:for-each 来解决问题,更不需要嵌套 xsl:for-each.

事实上,可以使用单个 XPath 表达式来选择所需的 ItemA 元素

/*/ItemA[AName = 'BBC' 
       and 
         not(ANum = /*/ItemB/tempBNum)
        ]

因此,计算上述 XPath 表达式并将结果复制到输出的简单 XSLT 转换为:

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

 <xsl:template match="/">
     <xsl:copy-of select=
     "/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<myData>
    <ItemA>
        <ANum>0213</ANum>
        <AName>OOC</AName>
    </ItemA>
    <ItemA>
        <ANum>0031</ANum>
        <AName>BBC</AName>
    </ItemA>
    <ItemA>
        <ANum>0214</ANum>
        <AName>BBC</AName>
    </ItemA>
    <ItemA>
        <ANum>0044</ANum>
        <AName>BBC</AName>
    </ItemA>
    <ItemB>
        <tempBNum>0031</tempBNum>
    </ItemB>
    <ItemB>
        <tempBNum>0044</tempBNum>
    </ItemB>
</myData>

生成所需的正确结果

<ItemA>
   <ANum>0214</ANum>
   <AName>BBC</AName>
</ItemA>

如果我们只需要文本节点的值,只需使用 string()函数:

string(/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)])

那么修改后的变换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
     <xsl:copy-of select=
     "string(/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)])"/>
 </xsl:template>
</xsl:stylesheet>

当应用于同一个 XML 文档(上面),会产生:

    0214
    BBC

注意:如果性能开始变得重要,那么下一步可能会使用键来提高转换效率。

You don't need to use any xsl:for-each to solve the problem, much more you don't need nested xsl:for-each.

In fact, the wanted ItemA elements can be selected with a single XPath expression:

/*/ItemA[AName = 'BBC' 
       and 
         not(ANum = /*/ItemB/tempBNum)
        ]

Therefore a simple XSLT transformation that evaluates the above XPath expression and copies the result to the output is:

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

 <xsl:template match="/">
     <xsl:copy-of select=
     "/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)]"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied to the provided XML document:

<myData>
    <ItemA>
        <ANum>0213</ANum>
        <AName>OOC</AName>
    </ItemA>
    <ItemA>
        <ANum>0031</ANum>
        <AName>BBC</AName>
    </ItemA>
    <ItemA>
        <ANum>0214</ANum>
        <AName>BBC</AName>
    </ItemA>
    <ItemA>
        <ANum>0044</ANum>
        <AName>BBC</AName>
    </ItemA>
    <ItemB>
        <tempBNum>0031</tempBNum>
    </ItemB>
    <ItemB>
        <tempBNum>0044</tempBNum>
    </ItemB>
</myData>

the wanted, correct result is produced:

<ItemA>
   <ANum>0214</ANum>
   <AName>BBC</AName>
</ItemA>

If we want just the values of the text nodes, just use the string() function:

string(/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)])

Then the so modified transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
     <xsl:copy-of select=
     "string(/*/ItemA[AName = 'BBC' and not(ANum = /*/ItemB/tempBNum)])"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the same XML document (above), produces:

    0214
    BBC

Note: If performance starts to matter, using keys could be the next step to increase the efficiency of the transformation.

小ぇ时光︴ 2025-01-15 08:46:48

您无法中断,但可以添加条件以确保没有 previous-sibling ItemAObj/ANum = tempBNum

You can't break, but you add the condition to make sure for no previous-sibling ItemAObj/ANum = tempBNum

萝莉病 2025-01-15 08:46:48

这可以通过一种不同的方式来实现,需要 for-each 迭代项目并依次检查它。相反,您可以使用键来查找某个数字是否存在 ItemB 元素

<xsl:key name="itemB" match="ItemB" use="tempBNum" />

然后您可以简单地匹配不存在 ItemB< 的 itemA 元素ANNum 中出现的 /strong> 元素

<xsl:apply-templates select="ItemA[AName='BBC'][not(key('itemB', ANum))]" />

这是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="itemB" match="ItemB" use="tempBNum" />

   <xsl:template match="/myData">
      <xsl:apply-templates select="ItemA[AName='BBC'][not(key('itemB', ANum))]" />
   </xsl:template>

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

当应用于示例 XML 时,输出如下:

<ItemA>
   <ANum>0214</ANum>
   <AName>BBC</AName>
</ItemA>

This can be achieved in a different way, with the need for the for-each to iterate over the items and checking it one on turn. Instead, you could make use of a key to look up whether the ItemB elements exist for a number

<xsl:key name="itemB" match="ItemB" use="tempBNum" />

Then you can simply match itemA elements where there are no ItemB elements present for the ANNum

<xsl:apply-templates select="ItemA[AName='BBC'][not(key('itemB', ANum))]" />

Here is the full XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="itemB" match="ItemB" use="tempBNum" />

   <xsl:template match="/myData">
      <xsl:apply-templates select="ItemA[AName='BBC'][not(key('itemB', ANum))]" />
   </xsl:template>

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

When applied to your sample XML, the following is output:

<ItemA>
   <ANum>0214</ANum>
   <AName>BBC</AName>
</ItemA>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文