如何使用XSLT合并两个XML文档中对应元素的属性?
解决XML文档中
<w>元素属性合并问题 我来帮你搞定这个问题!你的核心需求是把两个XML里对应xml:id的<w>元素的orig和norm属性合并到同一个元素中,原代码的问题在于没根据当前<w>的xml:id去匹配xml2里的对应项,而是直接捞了所有norm属性值,导致结果不对。下面是具体的解决方案:
问题分析
你原来写的document('xml2.xml')//@norm会选中xml2里所有<w>元素的norm属性,结果每个<w>都会被添上一堆norm值的拼接内容,完全不是你要的对应匹配效果。我们得靠xml:id把两个文档里的<w>元素关联起来。
正确的XSLT实现
这里推荐用<xsl:key>来高效索引xml2里的<w>元素,再根据当前<w>的xml:id精准匹配对应属性:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.tei-c.org/ns/1.0" xmlns="http://www.tei-c.org/ns/1.0" version="2.0"> <xsl:output method="xml" indent="no"/> <!-- 定义索引:用xml:id关联xml2中的w元素 --> <xsl:key name="w-by-id" match="w" use="@xml:id"/> <!-- 身份模板:原样复制所有未特殊处理的节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理xml1的w元素,添加对应norm属性 --> <xsl:template match="w"> <xsl:copy> <!-- 复制原有的所有属性(包括orig和xml:id) --> <xsl:apply-templates select="@*"/> <!-- 通过索引找到xml2中同id的w元素,取出norm属性 --> <xsl:attribute name="norm"> <xsl:value-of select="key('w-by-id', @xml:id, document('xml2.xml'))/@norm"/> </xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码解释
<xsl:key>索引定义:w-by-id这个索引会把xml2里的每个<w>元素按它的xml:id值归类,后续查找时能快速定位到对应元素,文档越大效率优势越明显。- 身份模板:保证除了
<w>之外的所有内容(比如<text>、<seg>、<l>这些结构标签)都原样复制,不破坏原有文档结构。 <w>元素处理逻辑:- 先复制当前
<w>的所有原有属性(比如xml:id和orig); - 用
key('w-by-id', @xml:id, document('xml2.xml'))从xml2里揪出和当前<w>同xml:id的元素,再把它的norm属性值加到当前元素上。
- 先复制当前
验证效果
用你提供的xml1和xml2作为输入,运行上面的XSLT后,就能得到你想要的输出:
<text> <seg type="stanza" n="1"> <l n="1"> <w xml:id="1" orig="Haile" norm="Hail"/> <w xml:id="2" orig="," norm=","/> <w xml:id="3" orig="sterne" norm="star"/> <w xml:id="4" orig="superne" norm="supernal"/> <w xml:id="5" orig="!" norm="!"/> </l> </seg> </text>
内容的提问来源于stack exchange,提问作者MB-OX
相关产品推荐
相关产品推荐

