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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/350641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 12:14:43  来源:igfitidea点击:

Check if the node set contains any value in XSLT

xmlxslt

提问by Alex

I need some help with XSLT syntax. Here is my scenario, I have an XML file that needs to be transformed in to a different look and feel of XML file, I have several sections where if particular node set don't contain any value the whole section shouldn't be processed.

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

Here is an example of 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

xml截图

Here is my XSLT with the if statement that don't work right

这是我的 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>

So as you can see I basically want all nodes (VALUE1, VALUE2, VALUE3, etc) to have values or else don't process and move on to the next section

因此,正如您所看到的,我基本上希望所有节点(VALUE1、VALUE2、VALUE3 等)都具有值,否则不进行处理并转到下一部分

(If you cannot see the XML come thought, I also made a screen shot)

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

回答by Chris Marasti-Georg

You are trying to match xml elements with names "Level1", "Level2", etc... that don't exist in the document. Then, you are looking for a VALUE1 attribute on the last element.

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

I thinkyou want something like this:

你想要这样的东西:

<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>

This will add a new MyDate element as long as everyvalue in the corresponding Date element is not empty.

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

What it does is

它的作用是

  1. Create a new MyDates element for each Dates element.
  2. Check each Date element. The *matches all children. [.='']means "is empty". Finally, it wraps all that in a not. This means the if only passes if there is not any child that is empty.
  3. If it has no children that are empty, it creates a new MyDate element with a copy of each value.
  1. 为每个 Dates 元素创建一个新的 MyDates 元素。
  2. 检查每个日期元素。在*所有儿童相匹配。[.='']意思是“是空的”。最后,它将所有这些都包装在一个 not 中。这意味着 if 只有在没有任何孩子为空时才通过。
  3. 如果它没有空的子元素,它会创建一个新的 MyDate 元素,其中包含每个值的副本。

You may also want to check the W3Schools XSLand XPathtutorials.

您可能还想查看 W3Schools XSLXPath教程。

回答by Dimitre Novatchev

You have not defined well what does it mean for "a node to have value".

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

Most probably, you will consider an element, that has a white space-only text child, not to have value. In this case, below is one solution:

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

<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>

This templete for a "Date" element will not be matched if the "Date" contained even one child element, that has no content or only white space.

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

When this transformation is applied on the following XML document:

当此转换应用于以下 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> 

The correct result is produced:

产生了正确的结果

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

回答by SO User

<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>

回答by SO User

I think you can do this also. Instead of checking a node. VALUE1/text() will check if the node has some text within. You might want to make sure that there is no white space for these. Also, you can see if the VALUE1 element has a child node.

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

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

</xsl:if>   

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

</xsl:if>  

回答by pinto

The @ is redundant - it refers to XML attributes.

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

You are trying to test for an element so just drop the @.

您正在尝试测试元素,因此只需删除 @。

In addition:

此外:

  • Level1/Level2/Level3 is wrong
  • You are testing for VALUE1 only but want to test for all values (which can be done with *)
  • Level1/Level2/Level3 错误
  • 您仅测试 VALUE1 但想要测试所有值(可以使用 * 完成)

回答by user2292708

<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>