3

我正在使用 XSLT 转换来自两个不同源 XML 的信息。第一个源中的每个相关节点在第二个源文件中都有一个具有等效“id”属性的节点,其中包含需要合并的额外信息。第二个源中没有匹配的任何节点都无关紧要,因此第一个源需要驱动结果。

这是问题的简化版本:

XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:two="http://www.mycompany.com/schemas/1.0">

    <xsl:param name="secondDoc" as="document-node()" />

    <xsl:template match="/">
        <Employees>
            <xsl:apply-templates match="$secondDoc/two:People/two:Person" />
        <Employees>
    </xsl:template>

    <xsl:template match="two:Person">
        <Employee>
            <xsl:value-of select="/Employees/Employee[@id='@id']/FirstName" />
            <xsl:value-of select="two:LastName" />
        </Employee>
    </xsl:template>

</xsl:stylesheet>

第一个来源:

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
    <Employee id="1">
        <FirstName>John</FirstName>
    </Employee>
</Employees>

第二来源:

<?xml version="1.0" encoding="UTF-8"?>
<People xmlns="http://www.mycompany.com/schemas/1.0">
    <Person id="1">
        <LastName>Doe</LastName>
    </Person>
</People>

我尝试使用的方法是创建与第二个源使用的命名空间前缀匹配的模板,然后从模板中匹配到等效节点。问题是我不确定如何将 XPath 返回到根模板。当然,value-of 语句失败了。

我尝试的一种方法是将 xsl:with-param 添加到 xsl:apply-templates> 并将匹配节点作为变量发送到模板。如果我手动选择了一个节点(Employee[1]),这可行,但由于 with-param 似乎没有采用 apply-templates 选择的上下文,我不确定如何将“id”属性绑定在一起.

有没有办法引用回根模板,还是我走错了路?

编辑:我想到了一个可能的解决方案,尽管它可能不是最干净的。我可以将“Employees”节点作为参数传递给模板,然后匹配模板内特定员工的“id”标签,并使用生成的节点作为参考。这看起来像是在这个示例中传递根节点,但实际上这是整个 XSL 的一小部分。希望有更简单的方法。

4

2 回答 2

2

这是一种略有不同的方法,采用您所说的关于驱动结果的第一个来源的内容,并调用 seoncd 来源。这可能有用:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:two="http://www.mycompany.com/schemas/1.0" version="2.0">

<xsl:variable name="source2" select="doc('source2.xml')"></xsl:variable>

<xsl:template match="/">
    <Employees>
        <xsl:apply-templates select="/Employees/Employee"/>
    </Employees>
</xsl:template>

<xsl:template match="Employee">
    <Employee>
        <xsl:value-of select="FirstName" />
        <xsl:text> </xsl:text>
        <xsl:value-of select="$source2/two:People/two:Person[@id=current()/@id]/two:LastName" />
    </Employee>
</xsl:template>

</xsl:stylesheet>
于 2013-10-23T20:13:13.933 回答
2

使用变量存储对主输入文档根节点的引用:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:two="http://www.mycompany.com/schemas/1.0">

    <xsl:param name="secondDoc" as="document-node()" />

    <xsl:variable name="main-root" select="/"/>

    <xsl:template match="/">
        <Employees>
            <xsl:apply-templates match="$secondDoc/two:People/two:Person" />
        <Employees>
    </xsl:template>

    <xsl:template match="two:Person">
        <Employee>
            <xsl:value-of select="$main-root/Employees/Employee[@id = current()/@id]/FirstName" />
            <xsl:value-of select="two:LastName" />
        </Employee>
    </xsl:template>

</xsl:stylesheet>

然后当然使用一个键进行交叉引用:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:two="http://www.mycompany.com/schemas/1.0">

    <xsl:param name="secondDoc" as="document-node()" />

    <xsl:key name="id" match="Employee" use="@id"/>
    <xsl:variable name="main-root" select="/"/>    
    <xsl:template match="/">
        <Employees>
            <xsl:apply-templates match="$secondDoc/two:People/two:Person" />
        <Employees>
    </xsl:template>

    <xsl:template match="two:Person">
        <Employee>
            <xsl:value-of select="key('id', @id, $main-root)/FirstName" />
            <xsl:value-of select="two:LastName" />
        </Employee>
    </xsl:template>

</xsl:stylesheet>
于 2013-10-24T09:04:39.280 回答