使用 XSL 转换合并两个 XML 文件
Posted
技术标签:
【中文标题】使用 XSL 转换合并两个 XML 文件【英文标题】:Merging two XML files using XSL transformation 【发布时间】:2020-06-16 07:13:42 【问题描述】:我一直在尝试将两个 xml 文件合并到另一个 XML 中,并使用 XSL 将两者的输出合并,但未能成功。 xml 相当大,所以我只包括一小部分。 我真的迷失在这个任务上。我可以转换单个 XML 文件,但合并两个是我从未做过的事情,也找不到与我的具体案例相关的太多信息。
XML 1:
<Games>
<Game>
<Date>01/05/2019</Date>
<PlayerID>454asdsad</PlayerID>
<Place>1</Place>
<GameID>CpsQf125AFy</GameID>
<Payment currency="gbp">50</Payment>
</Game>
.....repeats the above many times with different values.
</Games>
XML 2:
<Players>
<Player>
<Title>Mr</Title>
<Lastname>Doe</Lastname>
<Firstname>John</Firstname>
<IDnumber>454asdsad</IDnumber>
<Address>Streetname</Address>
</Player>
.....repeats the above many times with different values.
</Players>
预期结果:
<Games>
<Place>
<Date>
<Game>
<Title>Mr</prefix>
<Lastname>Doe</Lastname>
<Firstname>John</Firstname>
<IDnumber>454asdsad</IDnumber>
<Address>Streetname</Address>
<Date>01/05/2019</Date>
<PlayerID>454asdsad</Player>
<Place>1</Place>
<GameID>CpsQf125AFy</GameID>
<Payment currency="gbp">50</Payment>
</Game>
</Date>
<Date> ...if there are more dates is the same place as above.
<Game>
....information
</Game>
</Date>
</Place>
<Place> ...another place
<Date>
<Game>
...all the information like above, with the appropriate next values from both XML's.
</Game>
</Date>
<Date> ...if there are more dates is the same place as above.
<Game>
....information
</Game>
<Date>
</Place>
...repeats same thing and format until the end.
</Games>
【问题讨论】:
您的处理器是否支持 XSLT 2.0? ——附言元素名称不能以数字开头;如果这真的是您的 XML 2 的样子,那么您将无法在 XSLT 中使用它。 应该可以的。是的,我知道标签,那是我的错误。最终结果应该不是,忘记删除了。 什么决定了要合并的元素?只是他们的立场?或者任何元素值?我无法识别来自两个输入的元素似乎共有的样本数据中的任何合并或分组键。 并说明您可以使用哪个 XSLT 处理器和/或 XSLT 版本,例如 XSLT 3 有xsl:merge
并且在 XSLT 2 中 for-each-group
可以轻松处理来自不同文档的节点(而 Muenchian 分组在 XSLT 1 中,使用不同的文档更难基于键)。
基本上它们是由一个中的“PlayerID”和另一个中的“IDNumber”连接的。如果它们同时存在,则它会加入信息。 XSLT 2 将是理想的选择。我不确定我可以使用 3.0,也不确定我以前没有使用过。我之前使用过 for-each 只是不知道如何使用 2 个单独的 xml 来工作和应用它
【参考方案1】:
如果您知道for-each-group
,那么您应该可以毫无问题地从两个文档中提取元素,例如<xsl:for-each-group select="/Games/Game, doc('file2.xml')/Players/Player" group-by="PlayerID, IDnumber">
,分组键将由存在该元素的PlayerID
和存在该元素的IDnumber
组成,只要不存在具有两个子元素的元素,该方法应该是安全的或可以更正为group-by="(PlayerID, IDnumber)[1]"
到如果没有,请选择一个键。
如果还需要按Place
分组,您可以嵌套另一个for-each-group select="current-group()" group-by="Place"
或使用复合键。
【讨论】:
我用过for-each,但从来没有for-each-group。但我会试一试。这对我来说仍然很新鲜。 使用它可以做到你所说的,它的进步。但它只输出 Games xml 和来自 Players xml 的 ID 编号。当我尝试手动添加它们时,它们不会输出或输出循环。我知道我很接近,但不知道现在如何让它们都显示在两个列表中【参考方案2】:这有两个部分:
分组,先就地,后日期
加入,从 personID 选择的第二个文件中获取数据。
分组基本是
<xsl:for-each-group select="Game" group-by="Place">
<Place>
<xsl:for-each-group select="current-group()" group-by="Date">
<Date>
<xsl:for-each select="current-group()">
<Game>
XXXXX
<xsl:copy-of select="*"/>
而在XXXXX你需要做join,基本上就是
<xsl:copy-of select="key('player-id', PlayerID, $players-xml')/*"/>
其中$players-xml是Players.xml文件,key定义为
<xsl:key name="player-id" match="Player" use="IDNumber"/>
【讨论】:
非常感谢,这帮助很大。并不像我想象的那么容易,因为我需要组织和展示事物的方式,但是根据您给我的结构,我设法找到了一种方法:)以上是关于使用 XSL 转换合并两个 XML 文件的主要内容,如果未能解决你的问题,请参考以下文章
使用 Saxon 对 Msi 文件 (xml) 运行 XSL 转换