【问题标题】:Follow Up on question that got solvend using Muenchian Grouping跟进使用 Muenchian Grouping 解决的问题
【发布时间】:2019-07-18 11:01:15
【问题描述】:

所以,我之前的帖子是这样的: Matching the first element when it can occure in different places of the hierarchy?

Muenchian Group 似乎工作了,但现在我有一个问题,我有多个 a。比如这样的

<x>
<a>
    <b>
        <d value="1"></d>
    <b/>
    <b>
        <c>
            <d value="2"></d>
            <d value="1"></d>
        </c>
        <d value="1">
        <d value="2">
    <b/>
</a>
<a>
    <b>
        <d value="3"></d>
    <b/>
    <b>
        <c>
            <d value="1"></d>
            <d value="2"></d>
        </c>
        <d value="1">
        <d value="3">
    <b/>
</a>
</x>

您可以看到,我在 a[1] 和 a[2] 中有 d/@value="1"。我想摆脱在这个特定的 a 中尚未出现的每个 d 值。所以在这里我想保留第一个 value="1" 和 value="2" a[1] 和 a[2] 和第一个 value="3" 在 a[2] 中并摆脱所有其他人。

导致这样的输出:

<x>
<a>
    <b>
        <d value="1"></d>
    <b/>
    <b>
        <c>
            <d value="2"></d>
        </c>
    <b/>
</a>
<a>
    <b>
        <d value="3"></d>
    <b/>
    <b>
        <c>
            <d value="1"></d>
            <d value="2"></d>
        </c>
    <b/>
</a>
</x>

我试过这样:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="d-by-value" match="d" use="@value" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- remove duplicate d's -->
<xsl:template match="a//d[count(. | key('d-by-value', @value)[1]) != 1]"/>

</xsl:stylesheet> 

这导致整个 xml 中只有第一个 d/@value="1" 保留(因为整个文件中的总计数当然 >1 在不同的 a 中,所以我也尝试了这个:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="d-by-value" match="d" use="@value" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- remove duplicate d's -->
<xsl:template match="a//d[count(. | key('d-by-value', @value)[1]) != 1]"/>

 <xsl:template match="d" name="remove-d"/>

    <xsl:template match="paragr">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="node()"/>
            <xsl:for-each select=".//d[count(. | key('d-by-value', @value)[1]) != 1]) = 1]">
                <xsl:call-template name="remove-d"/>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet> 

但这似乎摆脱了所有的d。有什么想法吗?

编辑:更正了 xsl:for-each 选择。犯了一个复制/粘贴错误并纠正了那个有价值的东西,见下面的评论。

【问题讨论】:

  • 您在所需输出中的第二个a 中出现了两次&lt;d value="1"&gt;?那是对的吗?谢谢!
  • 哦,不。我会编辑它。对不起,我的错。

标签: xml xslt xpath


【解决方案1】:

如果要删除给定a 元素的重复值,则需要在键匹配中引用a

<xsl:key name="d-by-value" match="d" use="concat(generate-id(ancestor::a), '|', @value)" />

在这里,generate-id 将为 XML 中的节点创建一个唯一代码。

然后,在使用密钥时,您需要在模板匹配中使用类似的逻辑

<xsl:template match="a//d[count(. | key('d-by-value', concat(generate-id(ancestor::a), '|', @value))[1]) != 1]"/>

试试这个 XSLT

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:strip-space elements="*"/>

    <xsl:key name="d-by-value" match="d" use="concat(generate-id(ancestor::a), '|', @value)" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- remove duplicate d's -->
    <xsl:template match="a//d[count(. | key('d-by-value', concat(generate-id(ancestor::a), '|', @value))[1]) != 1]"/>
</xsl:stylesheet> 

【讨论】:

  • 生成-id()。有趣的。还不知道。完全符合我的要求。谢谢。
猜你喜欢
  • 2015-04-10
  • 2013-09-27
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多