簡體   English   中英

XSLT將多個源文檔合並到組合節點中

[英]XSLT merge multiple source documents into combined nodes

我正在嘗試將兩個或多個源文檔的內容組合到單個輸出文檔中,其中內容應位於相同的節點中。

這兩個源文件是Resources.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="ButtonCancelString">
    <value>Cancel</value>
  </data>
  <data name="ButtonCloseString">
    <value>Close</value>
  </data>
</root>

和Resources.de.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="ButtonCancelString">
    <value>Abbrechen</value>
  </data>
  <data name="ButtonCloseString">
    <value>Schließen</value>
  </data>
</root>

我使用以下轉換(combine.xslt):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/empty">
        <root>
            <constants>
                <xsl:apply-templates select="document('Resources.resx')">
                    <xsl:with-param name="language" select="'en'"/>
                </xsl:apply-templates>
                <xsl:apply-templates select="document('Resources.de.resx')">
                    <xsl:with-param name="language" select="'de'"/>
                </xsl:apply-templates>
            </constants>
        </root>
    </xsl:template>

    <xsl:template match="/root/data">
        <xsl:param name="language"/>
        <xsl:element name="const">
            <xsl:attribute name="name">
                <xsl:value-of select="@name"/>
            </xsl:attribute>
            <xsl:element name="text">
                <xsl:attribute name="lang" >
                    <xsl:value-of select="$language"/>
                </xsl:attribute>
                <xsl:value-of select="value"/> 
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

我在一個空的xml上運行轉換:

<?xml version="1.0" encoding="UTF-8"?>
<empty/>

生成的文檔是這樣的(刪除了一些噪音):

<root >
    <constants>
        <const name="ButtonCancelString">
            <text lang="en">Cancel</text>
        </const>
        <const name="ButtonCloseString">
            <text lang="en">Close</text>
        </const>
        <const name="ButtonCancelString">
            <text lang="de">Abbrechen</text>
        </const>
        <const name="ButtonCloseString">
            <text lang="de">Schließen</text>
        </const>
    </constants>
</root>

但是,我需要以下輸出,而不是重復的節點:

<?xml version="1.0" encoding="UTF-8"?>
<root >
    <constants>
        <const name="ButtonCancelString">
            <text lang="en">Cancel</text>
            <text lang="de">Abbrechen</text>
        </const>
        <const name="ButtonCloseString">
            <text lang="en">Close</text>
            <text lang="de">Schließen</text>
        </const>
    </constants>
</root>

有沒有辦法使用transfomations實現這一目標?

由於你的樣式表有version="2.0"我已經編寫了一個XSLT 2.0解決方案,我會使用密鑰或for-each-group ,在下面的示例中我使用了密鑰。 它期望Resources.resx作為主要輸入文檔,並且具有Resource.lang.resx形式的字符串序列的參數用於其他文檔:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="xs fn">

    <xsl:param name="resource-urls" as="xs:string*" select="'Resources.de.resx', 'Resources.es.resx'"/>

    <xsl:variable name="resource-docs" as="document-node()*" select="for $url in $resource-urls return doc($url)"/>

    <xsl:key name="name" match="data" use="@name"/>

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/root">
        <root>
            <constants>
                <xsl:apply-templates select="data"/>
            </constants>
        </root>
    </xsl:template>

    <xsl:template match="/root/data">
        <const name="{@name}">
          <xsl:apply-templates select="., for $doc in $resource-docs return key('name', @name, $doc)" mode="value"/>
        </const>
    </xsl:template>

    <xsl:template match="/root/data" mode="value">
        <xsl:variable name="name-tokens" select="tokenize(tokenize(document-uri(/), '/')[last()], '\.')"/>
        <xsl:variable name="language" as="xs:string" select="if ($name-tokens[3]) then $name-tokens[2] else 'en'"/>
        <text lang="{$language}">
          <xsl:value-of select="value"/>
        </text>
    </xsl:template>
</xsl:stylesheet>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM