XSLT / Muenchian 分组:如何从组中选择具有某些子元素的元素?

Posted

技术标签:

【中文标题】XSLT / Muenchian 分组:如何从组中选择具有某些子元素的元素?【英文标题】:XSLT / Muenchian grouping: how to select element with certain sub-element from group? 【发布时间】:2018-04-28 16:02:27 【问题描述】:

我希望能够从具有特定子元素的一组重复项(使用 Muenchian 分组完成)中选择一个元素。我的 XML 如下所示:

<waybill>
<shipment>
    <parcel>
        <sscc>SSCC1</sscc>
        <consignee>Receiver1</consignee>
        <date>Date1</date>
        <status>Status1</status>
    </parcel>
    <parcel>
        <sscc>SSCC2</sscc>
        <consignee>Receiver2</consignee>
        <attention>Note2</attention>
    </parcel>
    <parcel>
        <sscc>SSCC3</sscc>
        <consignee>Receiver3</consignee>
    </parcel>
    <parcel>
        <sscc>SSCC4</sscc>
        <consignee>Receiver4</consignee>
    </parcel>
    <parcel>
        <sscc>SSCC1</sscc>
        <consignee>Receiver1</consignee>
        <attention>Note1</attention>
        <date>Date2</date>
        <status>Status2</status>
    </parcel>
    <parcel>
        <sscc>SSCC3</sscc>
        <consignee>Receiver3</consignee>
        <attention>Note3</attention>
    </parcel>
</shipment>
</waybill>

我的 XSLT 看起来像这样:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" version="2.0">
<xsl:output method="text" version="1.0" encoding="ISO-8859-1" indent="yes"/>
<xsl:key name="ean" match="parcel" use="sscc"/>
<xsl:template match="/">
    <xsl:for-each select="/waybill/shipment/parcel[generate-id()=generate-id(key('ean',sscc))]">
        <xsl:value-of select="current()/sscc"/>
        <xsl:text>§</xsl:text>
        <xsl:value-of select="current()/consignee"/>
        <xsl:text>§</xsl:text>
        <xsl:value-of select="current()/attention"/>
        <xsl:text>&#xd;</xsl:text>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

现在的输出如下所示:

SSCC1§Receiver1§
SSCC2§Receiver2§Note2
SSCC3§Receiver3§
SSCC4§Receiver4§

所以我的 XSLT 现在将从分组元素中选择第一个命中,我希望得到的结果是:

SSCC1§Receiver1§Note1
SSCC2§Receiver2§Note2
SSCC3§Receiver3§Note3
SSCC4§Receiver4§

因此 XSLT 应该从具有最多数据的组中找到那些重复项。不是第一个或最后一个,而是具有某些子元素的那个(或者在我的最后一种情况下:子子元素)

在这种情况下,并非所有元素都有子元素(此处为 SSCC4),这些子元素应与它们拥有的数据一起使用(不应被忽略)。

从分组的相似元素中找到“最佳”元素的正确方法是什么?

非常感谢任何帮助:)

【问题讨论】:

【参考方案1】:

您可以从key() 导航,如下所示:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" version="2.0">
    <xsl:output method="text" version="1.0" encoding="ISO-8859-1" indent="yes"/>
    <xsl:key name="ean" match="parcel" use="sscc"/>

    <xsl:template match="/">
        <xsl:for-each select="/waybill/shipment/parcel[generate-id()=generate-id(key('ean',sscc))]">
            <xsl:variable name="group" select="key('ean',sscc)" />
            <xsl:value-of select="sscc"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="$group/consignee"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="$group/attention"/>
            <xsl:text>&#xd;</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

key('ean',sscc) 将选择当前组的所有&lt;parcel&gt; 元素和key('ean',sscc)/attention 它们下方的所有&lt;attention&gt; 元素。

在 XSLT 2.0+ 中,您还可以使用 &lt;xsl:for-each-group&gt;current-group() 函数获得相同的效果。

&lt;xsl:value-of&gt; 中使用key('ean',sscc)/attention 只会打印第一个匹配项的值,这似乎是您的意图。

没有必要像你一样明确地使用current()current() 旨在用于 XPath 谓词中,在普通的 select 表达式中它不会添加任何值。

【讨论】:

你好。我已将 sscc1 下的 元素添加到上面的原始 xml 中。我还需要输出日期和状态,但只有最后一个条目(此处为 Date2 / Status2)。我知道 [last()] 应该可以解决问题,但是我应该如何在选择使用键时使用它?我可以使用键选择分组 SSCC1 的最后一个元素吗? ($group/date)[last()]

以上是关于XSLT / Muenchian 分组:如何从组中选择具有某些子元素的元素?的主要内容,如果未能解决你的问题,请参考以下文章

Muenchian 分组 XSLT 1.0 多重分组

如何改进我的 Muenchian 分组 XSLT?

将 Muenchian 分组应用于 XSLT

XSLT:如何使用 Muenchian 分组将 XML 转换为文本文件

XSLT 和 Muenchian 分组, 多级样本

XSLT muenchian 在子节点中按值分组