使用 XSLT 基于 ID 从多个 xPath 中选择 XML 节点
Posted
技术标签:
【中文标题】使用 XSLT 基于 ID 从多个 xPath 中选择 XML 节点【英文标题】:Select XML Node from multiple xPath based on ID using XSLT 【发布时间】:2022-01-04 07:08:00 【问题描述】:我目前正在处理一项任务,我需要遍历 XML 文件的两个不同部分(两个文件之前合并到这个文件中)并搜索 ID。
如果文件的两个位置的 ID、颜色和数量值都匹配,我需要选择第二个文件 (fileB) 中的所有字段。
如果没有,那么我需要从第一个文件 (fileA) 中选择字段。
这是一个 XML 示例:
<root>
<fileA>
<data>
<id>123</id>
<color>Green</color>
<quantaties>5</quantaties>
</data>
<data>
<id>456</id>
<color>Red</color>
<quantaties>7</quantaties>
</data>
<data>
<id>789</id>
<color>Blue</color>
<quantaties>9</quantaties>
</data>
</fileA>
<fileB>
<data>
<id>456</id>
<color>Red</color>
<quantaties>7</quantaties>
<date>15-07-2021</date>
<reason>Internal</reason>
</data>
</fileB>
</root>
在上面的示例中,两个文件中都只有 id 456,颜色为红色,数量为 7。在这种情况下,我想从 fileB 填充那个。所以我想要的输出是:
<root>
<newFile>
<data>
<id>123</id>
<color>Green</color>
<quantaties>5</quantaties>
</data>
<data>
<id>456</id>
<color>Red</color>
<quantaties>7</quantaties>
<date>15-07-2021</date>
<reason>Internal</reason>
</data>
<data>
<id>789</id>
<color>Blue</color>
<quantaties>9</quantaties>
</data>
</newFile>
</root>
请记住,多个字段必须匹配,而不仅仅是 ID。还有颜色和数量,以便选择 fileB 数据。谁能帮我解决这个问题?挣扎了一段时间。
【问题讨论】:
“多个字段必须匹配” 我们是否事先知道这些字段的名称(如您的示例中的 ID、颜色和数量)? 是的。它始终是 ID、颜色和数量字段。它们的名称总是相同的。 【参考方案1】:我会这样做:
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="fileB" match="fileB/data" use="id||color||quantaties"/>
<xsl:template match="/root">
<xsl:copy>
<newFile>
<xsl:for-each select="fileA/data">
<xsl:copy>
<xsl:copy-of select="*, key('fileB', id||color||quantaties)/(* except (id|color|quantaties))"/>
</xsl:copy>
</xsl:for-each>
</newFile>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,这假定 color
不以数字开头或结尾 - 否则您应该在 key
值中插入分隔符。
或者你可以这样做:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<xsl:copy>
<newFile>
<xsl:for-each-group select="*/data" group-by="id, color, quantaties" composite="yes">
<xsl:copy>
<xsl:for-each-group select="current-group()/*" group-by="name()" >
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</newFile>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
【讨论】:
谢谢迈克尔。这是一些惊人的例子,正是我想要的。以上是关于使用 XSLT 基于 ID 从多个 xPath 中选择 XML 节点的主要内容,如果未能解决你的问题,请参考以下文章
使用带有多个表达式的祖先或自我选择 text() XSLT XPATH