👋您好,提前感谢您的任何建议!
XML A
元数据导出a
元素名称是自定义的,反映本地字段名称
元素子文本在内容、文档顺序上与 B 相同
<metadata>
<record>
<Title>Untitled</Title>
<Photographer>Gordon Parks</Photographer>
<Notes>An important photograph because (...)</Notes>
</record>
...
</metadata>
XML B
元数据导出b
元素名称反映了到都柏林核心元素/术语的配置映射
元素子文本在内容、文档顺序上与 A 相同
<metadata>
<record>
<title>Untitled</title>
<creator>Gordon Parks</creator>
<description>An important photograph because (...)</description>
</record>
...
</metadata>
所需输出
使用本地字段名称作为元素名称
将 DC 元素/项捕获为 @dc 值
<metadata>
<record>
<Title dc="title">Untitled</Title>
<Photographer dc="creator">Gordon Parks</Photographer>
<Notes dc="description">An important photograph because (...)</Notes>
</record>
...
</metadata>
目前的样式表
<xsl:template match="/">
<metadata>
<xsl:for-each select="XML_A/metadata/record">
<record>
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="name() != ''">
<!-- minor issue above: without this I believe I was selecting whitespace and/or other nodes...
...ERROR description: "Supplied element name is a zero-length string" -->
<xsl:element name="{name()}">
<!-- ACK -->
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:for-each>
</record>
</xsl:for-each>
</metadata>
</xsl:template>
关于
<!-- ACK -->
正如我上面所说,我相信 A 和 B 中具有相同子文本的序列节点是相同的。因此,对于 A 中每条记录的每个子节点,我认为我可以使用 either
position()
或 text()
匹配B中对应的节点。但是...
我尝试实现一个键来匹配 A 和 B 之间所需的元数据/记录(给定的 ID 元素值,未在 XML A 和 B 的示例中显示,可用于匹配记录)。
<xsl:key name="match_xml_b" match="record" use="b_id">
...
<xsl:attribute name="dc"
select="key('match_xml_b', a_id, document('XMLB.xml')/[text() = $a_text]/name()/>
...or...
<xsl:attribute name="dc"
select="key('match_xml_b', a_id, document('XMLB.xml')/[position() = $a_position]/name()/>
我认为我的语法对于选择
record
的子节点不正确,其中文本内容与 A 中当前节点的文本内容匹配(或者位置与 A 中当前节点的位置匹配)。此外,我不确定使用什么 XPath 语法来选择 B 中的元素名称,这正是我的所需输出中需要的。
我也尝试过一些没有钥匙的笨拙匹配,类似于......
<xsl:attribute name="dc"
select="document('XMLB.xml')/metadata/record[b_id = a_id]/[position() = $a_position]
(: how to use name() here? :)"/>
or...
<xsl:attribute name="dc"
select="document('XMLB.xml')/metadata/record[b_id = a_id]/[text() = $a_text]
(: how to use name() here? :)"/>
...不成功。
我这里的困难包括使用
record
或 position()
匹配 text()
的子元素的语法,以及检索匹配后的元素的 name。
如果允许通过匹配文本来链接元素,您可以执行类似以下操作:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="xmlB" select="document('XMLB.xml')"/>
<xsl:key name="keyB" match="*" use="text()" />
<xsl:template match="/metadata">
<metadata>
<xsl:for-each select="record">
<record>
<xsl:for-each select="*">
<xsl:copy>
<xsl:attribute name="dc" select="key('keyB', text(), $xmlB)/name()"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:for-each>
</record>
</xsl:for-each>
</metadata>
</xsl:template>
</xsl:stylesheet>
这需要 XSLT 2.0 或更高版本。