首页 > 解决方案 > XSL 中每个循环的条件 XSL

问题描述

我在这里有一个场景,我需要使用 XSLT 生成一个带有 newnode1 的 xml,方法是读取一个可以以“n”次传递的 xml node1 和一个也可以作为“n”次传递的 node2。这是我的xml的样子..

     <?xml version="1.0" encoding="UTF-8"?>
    <Node>
    <Node_1>
       <Line>1</Line>
       <Text>First node1</Text>
       <Desc>Desc1</Desc>
       <Cust>Cust1</Cust>
    </Node_1>
    <Node_1>
       <Line>2</Line>
       <Text>First node2</Text>
       <Desc>Desc2</Desc>
       <Cust>Cust2</Cust>
    </Node_1>
    <Node_2>
       <Line>1</Line>
       <ReadInd>Y</ReadInd>
       <WriteInd>Y</WriteInd>
       <UpdateInd>Y</UpdateInd>
    </Node_2>
    <Node_2>
       <Line>2</Line>
       <ReadInd>N</ReadInd>
       <WriteInd>N</WriteInd>
       <UpdateInd>N</UpdateInd>
    </Node_2>
    </Node>        

下面是我为此实现的 XSLT 代码,但我确实在运行时看到了性能问题,当我的输入 XML Node_1 和 Node_2 重复超过 100 个循环时,它需要更多时间。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version = "1.0"   
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">     
<xsl:template match = "/">   
<xsl:for-each select="Node/Node_1">
    <xsl:variable name="line" select="//Node_1/Line"/>
    <line><xsl:value-of select="Line"/></line>
    <text><xsl:value-of select="Text"/></text>
    <desc><xsl:value-of select="Desc"/></desc>
    <cust><xsl:value-of select="Cust"/></cust>
    <xsl:for-each select="/Node/Node_2">
        <xsl:if test="Line=$line">
            <readind><xsl:value-of select="ReadInd"/></readind>
            <writeind><xsl:value-of select="WriteInd"/></writeind>
            <updateind><xsl:value-of select="UpdateInd"/></updateind>
        </xsl:if>
    </xsl:for-each>
</xsl:for-each>
</xsl:template>    
</xsl:stylesheet> 

如您所见,我在另一个 xsl:for each 中使用了 xsl:for each,并在每次执行 xsl:for each 时使用了 if 条件来检查行 num。是否有一个简单的逻辑可以得到我的结果,除了从我尝试过的。

提前致谢。

标签: xmlxsltdb2

解决方案


您遇到的一个问题是如何定义line变量

<xsl:variable name="line" select="//Node_1/Line"/>

这将选择 XML 中所有Line元素下的所有Node_1元素。这意味着当您这样做时<xsl:if test="Line=$line">,无论Node_1您正在处理什么,这实际上都会返回 true,因此您将输出所有Node_2元素。

你应该像这样定义它

但是,为了高效查找,请考虑使用键

<xsl:key name="node2" match="Node_2" use="Line" />

然后你可以Node_2像这样选择元素

<xsl:for-each select="key('node2', $line)">

甚至像这样,因为在这种情况下不需要变量,因为当前节点仍在Node_1这一点上

<xsl:for-each select="key('node2', Line)">

试试这个 XSLT

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

<xsl:key name="node2" match="Node_2" use="Line" />

<xsl:template match="/">   
    <xsl:for-each select="Node/Node_1">
        <node>
        <line><xsl:value-of select="Line"/></line>
        <text><xsl:value-of select="Text"/></text>
        <desc><xsl:value-of select="Desc"/></desc>
        <cust><xsl:value-of select="Cust"/></cust>
        <xsl:for-each select="key('node2', Line)">
            <subnode>
            <readind><xsl:value-of select="ReadInd"/></readind>
            <writeind><xsl:value-of select="WriteInd"/></writeind>
            <updateind><xsl:value-of select="UpdateInd"/></updateind>
            </subnode>
        </xsl:for-each>
        </node>
    </xsl:for-each>
</xsl:template>    
</xsl:stylesheet> 

(注意,我添加了nodesubnode标签只是为了更容易看到Node_2与每个相关联的正确元素Node_1


推荐阅读