如何使用XSLT从另一个XML文档提供属性值?

时间:2019-05-09 13:52:09

标签: xml xslt xpath

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

这听起来很容易,但是我无法完全使代码正常工作,也无法使代码选择属性'norm'的单个值,而不是所有可用值。

我尝试使用命令

从xml2中选择属性的值
<xsl:value-of select="document('xml2.xml')//@norm"/>

但是所有要做的就是选择xml2中所有'norm'属性的值。

我还尝试为两个文档中的每个元素赋予唯一的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>

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

2 个答案:

答案 0 :(得分:0)

最好使用 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>

答案 1 :(得分:-1)

<xsl:output method="xml" indent="yes"/>
    <xsl:variable name="imp" select="document('Stanza1.xml')"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="l">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:for-each select="w">
                <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:copy-of select="$imp/text/seg/l/w[@xml:id = current()/@xml:id]/@norm"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
You may use like this