XSL:仅复制大型 XML 文件中具有重复属性值的节点
XSL: Only copy nodes which have a duplicate attribute value in a large XML file
这是我的输入类型:
<modifs>
<test>
<ref id="1"/>
<ref id="2"/>
<ref id="800"/>
<ref id="5000"/>
<ref id="10000"/>
<ref id="40000"/>
</test>
<modif id="1">content1</modif>
<modif id="2">content2</modif>
<modif id="3">content3</modif>
<modif id="4">content4</modif>
</modifs>
在这个输入中,第一个列表 "ref" 只是一个属性列表,第二个列表 "modif" 对我来说才是真正重要的。
我想要做的是仅显示 "ref" 列表中具有匹配 "id" 属性的 "modif" 节点:这里我会得到的是:
<modif>
<modif id="1">content1</modif>
<modif id="2">content2</modif>
</modifs>
我尝试处理这个问题,部分成功了。我所做的是检查 "modif" 节点的每个 @id 是否有前面匹配的 "ref"@id:
<xsl:template match="modifs">
<xsl:for-each select="./modif">
<xsl:if test="./@id=preceding::ids/id">
<xsl:element name="{local-name()}">
<xsl:for-each select="attribute::*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:value-of select="."/>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
但是,我目前正在处理一个非常大的 XML 文件(超过 200k 个 id),这种方法根本没有时间效率(适用于前一千个 id,需要 hours/days 在那之后)。
我很确定有办法解决它(使用 muenchian 分组?)但我真的不明白我应该做什么...
如果有人可以帮助我/解释我应该如何进行,那就太好了。
谢谢
这里不需要 muenchian 分组,尽管您可以使用键来查找 ref
元素是否存在
<xsl:key name="ref" match="ref" use="@id" />
然后,与XSLT identity template结合使用,只需要一个模板来匹配modif
没有对应ref
元素的元素
<xsl:template match="modif[not(key('ref', @id))]"/>
试试这个 XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="ref" match="ref" use="@id" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="modif[not(key('ref', @id))]"/>
<xsl:template match="test" />
</xsl:stylesheet>
这是我的输入类型:
<modifs>
<test>
<ref id="1"/>
<ref id="2"/>
<ref id="800"/>
<ref id="5000"/>
<ref id="10000"/>
<ref id="40000"/>
</test>
<modif id="1">content1</modif>
<modif id="2">content2</modif>
<modif id="3">content3</modif>
<modif id="4">content4</modif>
</modifs>
在这个输入中,第一个列表 "ref" 只是一个属性列表,第二个列表 "modif" 对我来说才是真正重要的。 我想要做的是仅显示 "ref" 列表中具有匹配 "id" 属性的 "modif" 节点:这里我会得到的是:
<modif>
<modif id="1">content1</modif>
<modif id="2">content2</modif>
</modifs>
我尝试处理这个问题,部分成功了。我所做的是检查 "modif" 节点的每个 @id 是否有前面匹配的 "ref"@id:
<xsl:template match="modifs">
<xsl:for-each select="./modif">
<xsl:if test="./@id=preceding::ids/id">
<xsl:element name="{local-name()}">
<xsl:for-each select="attribute::*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:value-of select="."/>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
但是,我目前正在处理一个非常大的 XML 文件(超过 200k 个 id),这种方法根本没有时间效率(适用于前一千个 id,需要 hours/days 在那之后)。 我很确定有办法解决它(使用 muenchian 分组?)但我真的不明白我应该做什么...
如果有人可以帮助我/解释我应该如何进行,那就太好了。
谢谢
这里不需要 muenchian 分组,尽管您可以使用键来查找 ref
元素是否存在
<xsl:key name="ref" match="ref" use="@id" />
然后,与XSLT identity template结合使用,只需要一个模板来匹配modif
没有对应ref
元素的元素
<xsl:template match="modif[not(key('ref', @id))]"/>
试试这个 XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="ref" match="ref" use="@id" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="modif[not(key('ref', @id))]"/>
<xsl:template match="test" />
</xsl:stylesheet>