如何在XSLT for-each循环中仅使用不同的值

时间:2015-10-01 08:34:50

标签: xslt

我正在尝试仅检索元素的不同值。这是我的XML:

<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cF">
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
    <property key="MeterClassTypeCode" value="cF"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cE">
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
    <property key="MeterClassTypeCode" value="cE"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cC">
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
    <property key="MeterClassTypeCode" value="cC"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cD">
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
    <property key="MeterClassTypeCode" value="cD"/>
</LaunchedMeterClass>

我想创建一个XPath来获取那些&#34; LaunchedMeterClass&#34;节点具有<property key="ClusterContractUUID">的唯一值。目前,我正在使用以下内容:

<xsl:for-each select="./descendant::LaunchedMeterClass">
    <xsl:choose>
        <xsl:when test="./property/@key='ClusterContractUUID'">
            <contract-type>
                <property>
                    <xsl:attribute name="key">ClusterContractUUID</xsl:attribute>
                    <xsl:attribute name="value">
                        <xsl:value-of select="./property[@key='ClusterContractUUID']/@value"/>
                    </xsl:attribute>
                </property>
            </contract-type>
        </xsl:when>
        <xsl:otherwise>
            <contract-type>
                <property>
                    <xsl:attribute name="key">contractTypeCategory</xsl:attribute>
                </property>
            </contract-type>
        </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>

但这给了我所有的元素,包括重复:

<contract-type>
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>
<contract-type>
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>

如何编写仅提供不同值的XPath?我想要的输出是:

<contract-type>
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
</contract-type>
<contract-type>
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
</contract-type>

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

你也许可以尝试exslt的集合:distinct:

http://exslt.org/set/functions/distinct/

底部有一个例子。您的里程可能会有所不同。

答案 1 :(得分:0)

试试这个:

<强> XML:

<root>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cF">
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
    <property key="MeterClassTypeCode" value="cF"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cE">
    <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
    <property key="MeterClassTypeCode" value="cE"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cC">
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
    <property key="MeterClassTypeCode" value="cC"/>
</LaunchedMeterClass>
<LaunchedMeterClass id="584e348b-2a06-42d0-a858-b8909f579238-St-4M-Template-Standard-cD">
    <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
    <property key="MeterClassTypeCode" value="cD"/>
</LaunchedMeterClass>
</root>

<强> XSLT2.0

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="root">
    <xsl:for-each select="distinct-values(descendant::property[@key='ClusterContractUUID']/@value)">
        <contract-type>
            <property>
                <xsl:attribute name="key">ClusterContractUUID</xsl:attribute>
                    <xsl:attribute name="value">
                        <xsl:value-of select="."/>
                    </xsl:attribute>
                </property>
        </contract-type>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

<强>结果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <contract-type>
        <property key="ClusterContractUUID" value="c2cebd90-9265-4cea-8018-0aac6efcced2"/>
    </contract-type>
    <contract-type>
        <property key="ClusterContractUUID" value="d0c9f440-172c-49ad-9b95-cddce23f16fa"/>
    </contract-type>
</root>

修改 编辑以获得以下兄弟值。在上面的XSLT中,模板匹配是@ attributes侧,而不是如果模板匹配元素,我们可以轻松访问其他兄弟,祖先,后代等。

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
</xsl:template>

<xsl:template match="root">
    <root>
        <xsl:for-each select="descendant::property[@key='ClusterContractUUID' 
            and not(@value=preceding::property[@key='ClusterContractUUID']/@value)]">
              <contract-type>
                <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
                <xsl:apply-templates select="following-sibling::property"/>
            </contract-type>
        </xsl:for-each>
    </root>
</xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

这通常被称为“分组”。

在XSLT 2.0中,使用<xsl:for-each-group>构造。

在XSLT 1.0中,使用“Muenchian分组” - 您可以在自己喜欢的XSLT教科书或在线资源中找到它。

如果你真的需要在XPath而不是XSLT(你的问题不清楚)中做到这一点,你可以做的最好的是XPath 2.0 distinct-values()函数 - XPath 1.0中没有什么可以帮助你。