检查节点集是否包含XSLT中的任何值

时间:2008-12-08 19:48:51

标签: xml xslt

我需要一些XSLT语法方面的帮助。这是我的场景,我有一个XML文件,需要转换为XML文件的不同外观,我有几个部分,如果特定节点集不包含任何值,则不应处理整个部分。

以下是XML的示例:

<Dates>
    <Date>
        <VALUE1></VALUE1>
        <VALUE2></VALUE2>
        <VALUE3></VALUE3>
        <VALUE4></VALUE4>
        <VALUE5>3333</VALUE5>
    </Date>
    <Date>
        <VALUE1>AAAA</VALUE1>
        <VALUE2></VALUE2>
        <VALUE3>JJJJ</VALUE3>
        <VALUE4></VALUE4>
        <VALUE5>12345</VALUE5>
    </Date>
</Dates>

screenshot of xml

这是我的XSLT,if语句不能正常工作

<xsl:for-each select="Level1/Level2/Level3">
    <xsl:if test="@VALUE1!=''">                    
    <MyDates>               
            <value_1>
                <xsl:value-of select="VALUE1"/> 
            </value_1>
            <value_2>
                <xsl:value-of select="VALUE2"/> 
            </value_2>
            <value_3>
                <xsl:value-of select="VALUE3"/> 
            </value_3>
            <value_4>
                <xsl:value-of select="VALUE4"/> 
            </value_4>       
    </MyDates>
    </xsl:if>   
</xsl:for-each>

因此,您可以看到我基本上希望所有节点(VALUE1,VALUE2,VALUE3等)都有值,否则不处理并转到下一部分

(如果你看不到XML的想法,我也做了一个屏幕截图)

6 个答案:

答案 0 :(得分:12)

您正在尝试匹配文档中不存在的名称为“Level1”,“Level2”等的xml元素。然后,您正在寻找最后一个元素的VALUE1属性。

你想要这样的东西:

<xsl:for-each select="Dates">
    <MyDates>
        <xsl:for-each select="Date">
        <xsl:if test="not(*[.=''])">
            <MyDate>
                <value_1>
                    <xsl:value-of select="VALUE1"/> 
                </value_1>
                <value_2>
                    <xsl:value-of select="VALUE2"/> 
                </value_2>
                <value_3>
                    <xsl:value-of select="VALUE3"/> 
                </value_3>
                <value_4>
                    <xsl:value-of select="VALUE4"/> 
                </value_4>               
            </MyDate>
        </xsl:if>
        </xsl:for-each>
    </MyDates>
</xsl:for-each>

只要相应Date元素中的每个值都不为空,这将添加一个新的MyDate元素。

它做的是

  1. 为每个日期元素创建一个新的MyDates元素。
  2. 检查每个Date元素。 *匹配所有孩子。 [.='']表示“空”。最后,它包含了所有这些。这意味着如果没有任何子项为空,则if仅通过。
  3. 如果它没有空的子项,它会创建一个新的MyDate元素,并带有每个值的副本。
  4. 您可能还想查看W3Schools XSLXPath教程。

答案 1 :(得分:3)

你还没有很好地定义“节点有价值”是什么意思。

最有可能的是,您会考虑一个元素,它只有一个空格的文本子元素,没有值。 在这种情况下,下面是一个解决方案

<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="Date[not(*[not(normalize-space())])]">
       <xsl:copy-of select="."/>
     </xsl:template>

     <xsl:template match="text()"/>
</xsl:stylesheet>

如果“日期”甚至包含一个没有内容或只有空格的子元素,则“日期”元素的模板不会匹配。

将此转换应用于以下XML文档

<Dates>
    <Date>
        <VALUE1></VALUE1>
        <VALUE2>  </VALUE2>
        <VALUE3></VALUE3>
        <VALUE4></VALUE4>
        <VALUE5>3333</VALUE5>
    </Date>
    <Date>
        <VALUE1>AAAA</VALUE1>
        <VALUE2>1</VALUE2>
        <VALUE3>JJJJ</VALUE3>
        <VALUE4>1</VALUE4>
        <VALUE5>12345</VALUE5>
    </Date>
</Dates> 

产生了正确的结果

<Date>
    <VALUE1>AAAA</VALUE1>
    <VALUE2>1</VALUE2>
    <VALUE3>JJJJ</VALUE3>
    <VALUE4>1</VALUE4>
    <VALUE5>12345</VALUE5>
</Date>

答案 2 :(得分:2)

@是多余的 - 它指的是XML属性。

您正在尝试测试元素,所以只需删除@。

另外:

  • Level1 / Level2 / Level3错误
  • 您正在测试VALUE1但想测试所有值(可以使用*完成)

答案 3 :(得分:2)

<xsl:for-each select="Level1/Level2/Level3">
<MyDates>
    <xsl:if test="VALUE1!=''">
        <value_1>
            <xsl:value-of select="VALUE1"/>
        </value_1>
    </xsl:if>
    <xsl:if test="VALUE2!=''">
        <value_2>
            <xsl:value-of select="VALUE2"/>
        </value_2>
    </xsl:if>
    <xsl:if test="VALUE3!=''">
        <value_3>
            <xsl:value-of select="VALUE3"/>
        </value_3>
    </xsl:if>
    <xsl:if test="VALUE4!=''">
        <value_4>
            <xsl:value-of select="VALUE4"/>
        </value_4>
    </xsl:if>
</MyDates>

答案 4 :(得分:2)

我想你也可以这样做。而不是检查节点。 VALUE1 / text()将检查节点中是否有一些文本。您可能希望确保没有空白区域。此外,您可以查看VALUE1元素是否具有子节点。

<xsl:if test="VALUE1/text()">                    

</xsl:if>   

<xsl:if test="VALUE1/child::node()">                    

</xsl:if>  

答案 5 :(得分:0)

<xsl:template match="Dates">
<table border="1">
<tr bgcolor="#9acd32"><th>NAME</th><th>INVALUE</th></tr>
 <xsl:for-each select="Date">
  <xsl:if test="(VALUE1 != '') and (VALUE2 != '') and (VALUE3 != '') and (VALUE4 != '') and (VALUE5 != '')" >
     <tr><td>VALUE1</td><td><xsl:value-of select="VALUE1"></xsl:value-of></td></tr>
     <tr><td>VALUE2</td><td><xsl:value-of select="VALUE2"></xsl:value-of></td></tr>
     <tr><td>VALUE3</td><td><xsl:value-of select="VALUE3"></xsl:value-of></td></tr>
     <tr><td>VALUE4</td><td><xsl:value-of select="VALUE4"></xsl:value-of></td></tr>
     <tr><td>VALUE5</td><td><xsl:value-of select="VALUE5"></xsl:value-of></td></tr>
 </xsl:if>
 </xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>