如何合并具有“相同父亲”、相同方法和相同 id=0 的两个节点(使用 XSLT)?
Posted
技术标签:
【中文标题】如何合并具有“相同父亲”、相同方法和相同 id=0 的两个节点(使用 XSLT)?【英文标题】:how to merge two nodes having "the same father", the same method and the same id=0 (using XSLT)? 【发布时间】:2012-07-11 06:00:33 【问题描述】:我需要合并两个节点 street 因为它们是相同的:
父节点:纽约市 方法相同:修改 相同的ID:0必须合并属性值(请参阅本文末尾的输出文件)
这是输入文件:
<country>
<state id="NEW JERSEY">
<city id="NEW YORK">
<district id="BRONX" method="modify">
<street id="0" method="modify">
<attributes>
<temperature>98</temperature>
<altitude>1300</altitude>
</attributes>
</street>
<dadada id="99" method="modify" />
<street id="0" method="modify">
<attributes>
<temperature>80</temperature>
<streetnumber> 67 </streetnumber>
</attributes>
</street>
<dididi id="432" method="modify" />
</district>
</city>
</state>
预期输出:
<country>
<state id="NEW JERSEY">
<city id="NEW YORK">
<district id="BRONX" method="modify">
<street id="0" method="modify">
<attributes>
<temperature>80</temperature>
<altitude>1300</altitude>
<streetnumber> 67 </streetnumber>
</attributes>
</street>
<dadada id="99" method="modify" />
<dididi id="432" method="modify" />
</district>
</city>
</state>
</country>
请帮忙,我刚刚开始 XSLT
【问题讨论】:
两次发布本质上相同的问题并不能增加您在 SO 上获得问题的好答案的机会。 how to merge two nodes having "the same father" and adequate method (using XSLT)? 的可能重复项 这些问题(略有)不同,尽管它们看起来非常相似。输入文件格式肯定不同。另一个问题对方法有条件(CREATE then MODIFY and id = "MANHATTAN")。这里是方法 (MODIFY + MODIFY) 和 id="0" (number) @laurentngu:事实上,你(我怀疑你和约翰是同一个人)多年来一直在问同一个问题的许多细微变化——这表明你没有从答案,并且您有一个更深层次的问题,很可能是缺乏对 XSLT 的基本了解。我强烈建议您购买一本关于 XSLT 的好书并阅读和学习。继续发布相同的问题并且显然不理解答案显然对您没有任何好处。 @dimetre Novatchev 你好,我不是那个人/用户。今晚我一直在寻求有关 xslt 的帮助,因为我尝试从 Perl 转移到 xslt 以对我的 xml 文件进行排序。您提到的那个用户是我个人项目的临时远程参与者/助手。简而言之,我非常渴望学习 xslt 并在未来的项目中传播它。很抱歉我今晚的问题正在回忆其他帖子给您带来的不便,但这是使用和学习 xslt 的意愿 @laurentngu:自 2 月以来,我一直看到这个问题略有不同。请不要再问同一个问题的变体——如果你问不同的问题,这是完全可能的,甚至对你的学习更好。 【参考方案1】:我假设您对 XSLT 2.0 感兴趣,因为这就是您标记问题的方式。如果您需要等效的 XSLT 1.0,请告诉我。这个 XSLT 2.0 样式表应该可以解决问题...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[street]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="street" group-by="@method">
<xsl:apply-templates select="current-group()[1]" />
</xsl:for-each-group>
<xsl:apply-templates select="node()[not(self::street)]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="street/attributes">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:variable name="grouped-method" select="../@method" />
<xsl:for-each-group select="../../street[@method=$grouped-method]/attributes/*" group-by="name()">
<xsl:apply-templates select="current-group()[1]" />
</xsl:for-each-group>
<xsl:apply-templates select="comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
说明
第二个模板,匹配作为街道父元素的元素,将通过常用方法对子街道进行分组。对于每个组,仅复制组中的第一条街道。其余的被丢弃。
当组的第一条街道在第三个模板中具有其“属性”节点进程时,我们合并来自同一组的所有属性。 'attributes' 可能是 XML 文档中不幸的元素名称!通过查看具有相同街道父级(布朗克斯区)的所有联合街道的所有“属性”子节点并按元素名称分组来实现此分组。如果这样一个组中有多个元素,则只取第一个元素的值。
我不确定这是否正是您想要的,因为虽然街道属性由“父亲”节点 (Bronx) 合并,但它们并未在城市级别合并。这反映了您的问题的模棱两可。样本日期中街道的“父”节点是地区而不是城市。如果我弄错了,并且您想在城市级别进行分组,请澄清并更新您的问题。
【讨论】:
谢谢!是的,我需要“父亲节点布朗克斯”(区)的(街道)合并。所以你的转换工作正常,除了它返回<temperature>98</temperature>
而不是<temperature>80</temperature>
。如何修改 xslt 以获取第二条街道的值(最新值)?
Sean,请注意,这个用户(我相信和 John 是同一个人)已经问了好几个月的相同问题的变体——第三个你可能会变得愤怒当您一次又一次地看到相同的问题并有细微的变化时... :)
@DimitreNovaatchev 见上面的解释
用<xsl:apply-templates select="current-group()[last()]" />
替换最后一块<xsl:apply-templates select="current-group()[1]" />
以上是关于如何合并具有“相同父亲”、相同方法和相同 id=0 的两个节点(使用 XSLT)?的主要内容,如果未能解决你的问题,请参考以下文章