首页 > 解决方案 > 如何使用 XSLT 从另一个 XML 文档提供属性值?

问题描述

我有两个 XML 文档。一个(我们称之为 xml1)列出了一系列“w”元素,每个元素都有一个“orig”属性。另一个文档 (xml2) 列出了一系列相关的 'w' 元素,但具有不同的属性 ('norm')。我想合并这两个文档,这样我就只有一系列具有所有属性(“orig”和“norm”)的元素。

这听起来很简单,但我无法让代码正常工作,我无法让代码选择属性“规范”的单个值,而不是所有可用值。

我尝试使用命令从 xml2 中选择属性的值

<xsl:value-of select="document('xml2.xml')//@norm"/>

但这所做的只是选择 xml2 中所有“规范”属性的值。

我还尝试给两个文档中的每个元素一个唯一的 xml:id 属性,以便它们可以匹配,但是任何时候我使用条件语句来匹配它们,我都会得到相同的结果。

如果我使用“for each”命令,则不会选择任何元素。

这是 xml1 的示例:

    <text>
        <seg type="stanza" n="1">
            <l n="1">
                <w xml:id="1" orig="Haile"/>
                <w xml:id="2" orig=","/>
                <w xml:id="3" orig="sterne"/>
                <w xml:id="4" orig="superne"/>
                <w xml:id="5" orig="!"/>
            </l>
        </seg>
    </text>

这是 xml2 的示例:

    <text>
        <seg type="stanza" n="1">
            <l n="1">
                <w xml:id="1" norm="Hail"/>
                <w xml:id="2" norm=","/>
                <w xml:id="3" norm="star"/>
                <w xml:id="4" norm="supernal"/>
                <w xml:id="5" norm="!"/>
            </l>
        </seg>
    </text>

我想制作这个:

    <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>

到目前为止,我的 xslt 文件如下所示:

<?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"/>

    <!-- select the entirety of the document -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>    

    <!-- combine attributes from separate files -->
    <xsl:template match="//w">
        <xsl:copy>
             <xsl:apply-templates select="@*"/>
                  <xsl:attribute name="norm">
                       <xsl:value-of select="document('xml2.xml')//@norm"/>
                  </xsl:attribute>
        </xsl:copy>        
    </xsl:template>

</xsl:stylesheet>

如果可以的话,请帮助我。谢谢。

标签: xmlxsltxpath

解决方案


查找最好使用key处理。尝试(未经测试):

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="norm" match="w" use="@xml:id" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="w">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:copy-of select="key('norm', @xml:id, document('xml2.xml'))/@norm"/>   
    </xsl:copy>        
</xsl:template>

</xsl:stylesheet>

推荐阅读