【发布时间】:2019-02-04 09:59:42
【问题描述】:
你好 Stackoverflowers --
这是我第一次发帖。我遇到了一个令人沮丧的 XSLT 问题,尽管有各种假设的解决方案,但都未能解决。该方案是将一个 XML 文档 (#1) 基本转换为另一个 (#2) 的格式,以实现两个系统之间的互操作性。
XML doc #1 包含许多重复的元素,每个元素都包含一个单独的值。这些重复的元素需要转换为 doc #2 的替代元素,并包含 doc #1 中的相应值。
尽管进行了很多实验,但我似乎无法让它发挥作用。 doc #1 中的相关元素如下:
<mods:extension>
<rx:funder>Funder A</rx:funder>
<rx:projectid>Funder A code number</rx:projectid>
<rx:funder>Funder B</rx:funder>
<rx:projectid>Funder B code number</rx:projectid>
</mods:extension>
我需要将文档#2中的XML转换成如下:
<project_input>
<item>
<project>Funder A code number</project>
<funder_name>Funder A</funder_name>
</item>
<item>
<project>Funder B code number</project>
<funder_name>Funder B</funder_name>
</item>
</project_input>
但不幸的是,我转换的输出始终是这个的变体:
<project_input>
<item>
<project>Funder A code numberFunder B code number</project>
<funder_name>Funder AFunder B</funder_name>
</item>
</project_input>
...将值填充到单个元素中。
此刻的转变是这样的:
<xsl:if test="v3:extension">
<project_input>
<item>
<xsl:for-each select="v3:extension/rx:projectid">
<project>
<xsl:value-of select="."/>
</project>
</xsl:for-each>
<xsl:for-each select="v3:extension/rx:funder">
<funder_name>
<xsl:value-of select="."/>
</funder_name>
</xsl:for-each>
</item>
</project_input>
</xsl:if>
所以问题是,尽管正确的值在 doc #1 中成功循环,但它们在 doc #2 中没有正确输出。
我尝试过使用包含不同值的变体,但这也没有成功。令人沮丧的是,我以前做过这样的事情,但我这辈子都不记得了!堆栈上也已经描述了类似的场景,但那里提出的解决方案似乎在这个用例中不起作用。
谁能指出我遗漏的一些明显的东西?谢谢
更新的问题 - 请参阅下面的 cmets。这需要在 XSLT 1.0 中工作。我设法拼凑了一些东西。只要正确的数据被提取、排序和分组,它就工作了一半,但是缺少指定的 XML 元素。我可能遗漏了一些非常明显的东西。
有人可以帮帮我吗?这是 XSLT 1.0:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mods="http://www.loc.gov/mods/v3" xmlns:rx="http://example.com/rx"
version="1.0">
<xsl:output indent="yes"/>
<xsl:key use="rx:funder" match="mods:mods/mods:extension" name="groups" />
<xsl:template match="/">
<xsl:apply-templates select="mods:mods/mods:extension" />
</xsl:template>
<xsl:template match="mods:mods">
<rioxx2_project_output>
<xsl:for-each select="/mods:extension[generate-id(.)=generate-
id(key('groups', rx:funder))]">
<item>
<funder_name>
<xsl:value-of select="mods:extension/rx:funder/text()" />
</funder_name>
<project>
<xsl:value-of select="mods:extension/rx:projectid/text()" />
</project>
</item>
</xsl:for-each>
</project_input>
</xsl:template>
</xsl:stylesheet>
在 XSLT Fiddle 中:https://xsltfiddle.liberty-development.net/bFN1y8S/1
【问题讨论】:
-
你能说是否可以使用 XSLT 2.0 或更高版本吗?使用 XSLT 2.0,您可能会使用
xsl:for-each-group和group-starting-with。此外,是否总是存在projectid和funder元素?谢谢! -
谢谢蒂姆。应该包括那个。它是 XSLT 2.0。不会总是有
projectid和funder element存在。谢谢 -
如果不总是有
projectid或funder,那么您怎么知道在您的示例中“资助者A 代码”与“资助者A”而不是“资助者”一起使用乙”?谢谢! -
<xsl:if>应该检查 doc #1 中是否存在值,但事实上,在 doc #1 中建模 XML 的方式并不令人满意。它缺少一个额外的分层元素,以便projectid和funder可以正确分组。这将有助于解决我遇到的问题,但不幸的是我必须用我所拥有的东西来解决问题! :-(
标签: xml xslt transformation