3

XSLT を使用して、2 つの異なるソース XML から情報を変換しています。最初のソース内の関連する各ノードには、マージする必要がある追加情報を含む 2 番目のソース ファイル内の同等の「id」属性を持つノードがあります。一致しない 2 番目のソースのノードは重要ではないため、最初のソースが結果を駆動する必要があります。

問題の単純化されたバージョンを次に示します。

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>

私が使用しようとしている方法は、2 番目のソースで使用される名前空間プレフィックスに一致するテンプレートを作成し、テンプレート内の同等のノードに一致することです。問題は、ルート テンプレートに XPath で戻る方法がわからないことです。もちろん、value-of ステートメントは失敗します。

私が試した 1 つの方法は、xsl:with-param を xsl:apply-templates> に追加し、一致するノードを変数としてテンプレートに送信することです。ノードを手動で選択した場合 (Employee[1]) は機能しましたが、with-param は apply-templates select のコンテキストを使用していないように見えるため、「id」属性を結び付ける方法がわかりません。 .

ルート テンプレートを参照する方法はありますか、それとも間違った方法で行っていますか?

編集:最もクリーンではないかもしれませんが、可能な解決策を考えました。「Employees」ノードをパラメーターとしてテンプレートに渡し、テンプレート内の特定の従業員の「id」タグを照合して、結果のノードを参照として使用できます。これは、この例ではルート ノードを渡すように見えますが、実際には、これは XSL 全体の小さなセクションです。うまくいけば、もっと簡単な方法があります。

4

2 に答える 2

2

これは少し異なる方法で、結果を導く最初のソースについてあなたが言ったことを取り上げ、2 番目のソースを呼び出します。これは役に立つかもしれません:

<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 に答える