XSLT:如何检查多个节点是否应用于所有节点的某个值
我有以下简化的XML源代码:XSLT:如何检查多个节点是否应用于所有节点的某个值,xslt,xpath,grouping,Xslt,Xpath,Grouping,我有以下简化的XML源代码: <?xml version="1.0" encoding="UTF-8"?> <MVKE> <item> <MANDT>025</MANDT> <MATNR>000000000000000551</MATNR> <VMSTA>2</VMSTA> </item> <item> <MANDT>02
<?xml version="1.0" encoding="UTF-8"?>
<MVKE>
<item>
<MANDT>025</MANDT>
<MATNR>000000000000000551</MATNR>
<VMSTA>2</VMSTA>
</item>
<item>
<MANDT>025</MANDT>
<MATNR>000000000000000551</MATNR>
<VMSTA>2</VMSTA>
</item>
<item>
<MANDT>025</MANDT>
<MATNR>000000000000000551</MATNR>
<VMSTA>2</VMSTA>
</item>
</MVKE>
025
000000000000000551
2.
025
000000000000000551
2.
025
000000000000000551
2.
我需要比较
值。如果它们都是“2”,则目标XML中的我的标志值应为“true”,否则为“false”
我提出了以下XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml" encoding="UTF-8"/>
<xsl:template match="/">
<list>
<xsl:apply-templates select="MVKE"/>
</list>
</xsl:template>
<xsl:template match="MVKE">
<flag>
<xsl:for-each select="item">
<xsl:choose>
<xsl:when
test="(preceding-sibling::*[1]/VMSTA or self::*/VMSTA = current()/VMSTA) and (current()/VMSTA='2')">
<xsl:value-of select="'true'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'false'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</flag>
</xsl:template>
</xsl:stylesheet>
但输出总是很好
<?xml version="1.0" encoding="UTF-8"?>
<list>
<flag>truetruetrue</flag>
</list>
真的
因为
。我也用
上的键尝试过,但在
中也得到了3个值。如何正确比较3,并在
中仅获得一个值?我只是想把事情复杂化吗?你不需要为每一个都添加。假设上下文节点是一个MVKE
元素(如您的示例中),当所有VMSTA
元素的字符串值都等于2
(当存在任何其他值时,以下表达式返回true
):
这是因为item/VMSTA[not(.='2')]
隐式转换为布尔值。节点集的布尔值为true
当且仅当其为非空时。因此,item/VMSTA[not(.='2')]
只要选择至少一个节点,即存在字符串值不是2
的VMSTA
元素时,它就是true
。将表达式包装在not()
中会产生其否定,这是所需的结果
完整示例:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml" encoding="UTF-8"/>
<xsl:template match="/">
<list><xsl:apply-templates select="MVKE"/></list>
</xsl:template>
<xsl:template match="MVKE">
<flag><xsl:value-of select="not(item/VMSTA[not(.='2')])"/></flag>
</xsl:template>
</xsl:stylesheet>
只需使用:
not(/*/*/VMSTA[not(. = '2')])
如果存在一个元素/*/*/VMSTA
,其字符串值不同于字符串“2”
,则此XPath表达式的计算结果为false()
否则true()
这可能被称为“双重否定法则”我建议使用键获取一组节点,这些节点的值与
的值不同。如果该组只有一个节点,则所有值都相同:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:key name="dupes" match="VMSTA" use="."/>
<xsl:template match="/">
<xsl:variable name="vmsta-count"
select="count(//VMSTA[generate-id() =
generate-id(key('dupes', .))])"/>
<list>
<flag>
<xsl:choose>
<xsl:when test="$vmsta-count = 1">
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>false</xsl:text>
</xsl:otherwise>
</xsl:choose>
</flag>
</list>
</xsl:template>
</xsl:stylesheet>
真的
假的
当针对提供的源运行时,会导致:
<?xml version="1.0"?>
<list>
<flag>true</flag>
</list>
真的
但是,这是一个通用的案例解决方案,不关心实际价值,只关心价值差异
我希望这能有所帮助。很好的解释和示例。你好,lwburk,谢谢你的好解释和示例+1很好,我有同样的情况,我从来没有想到解决方案会这么简单:)谢谢你Dimitre的解释。我也必须看看XPATH。这是一个很好的替代方案,尽管有点黑客y、 但是,你又怎么能不欣赏一个优雅的黑客:)@MDeSchaepmeester:与其他答案相比,它肯定没有那么直接;至于OP,它肯定没有那么直接。它更一般,可能需要,也可能不需要,但弄清楚它很有趣。
<?xml version="1.0"?>
<list>
<flag>true</flag>
</list>