1

xmlns="myNS"ルートノードにxmlns属性()を追加したいトランスフォーメーションを書いています。

変換を適用すると、xmlns属性はいくつかの子要素に含まれます。

ルート要素にのみ適用するように変換を変更する方法を理解できません。

XML

<db:result xmlns:db="http://www.sonicsw.com/esb/service/dbservice">
    <db:resultSet version="1.1">
        <db:row>
            <id>a</id>
            <value1>b</value1>
            <value2>c</value2>
        </db:row>
        <db:row>
            <id>a</id>
            <value1>d</value1>
            <value2>e</value2>
        </db:row>
        <db:row>
            <id>a</id>
            <value1>f</value1>
            <value2>g</value2>
        </db:row>
        <db:row>
            <id>a</id>
            <value1>h</value1>
            <value2>i</value2>
        </db:row>
    </db:resultSet>
</db:result>

XSLT

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:db="http://www.sonicsw.com/esb/service/dbservice" 
    exclude-result-prefixes="db">
    <xsl:template match="/">
            <xsl:for-each-group select="//db:row" group-by="id">
                <xsl:sort select="id"/>
                    <xsl:apply-templates select="." mode="document"/>
            </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="db:row" mode="document">
        <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNS">
            <id><xsl:value-of select="id"/></id>
            <lines>
                <xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/>
            </lines>
        </root>        
    </xsl:template>

    <xsl:template match="db:row" mode="line">
        <line>
            <valueof1><xsl:value-of select="value1"/></valueof1>
            <valueof2><xsl:value-of select="value2"/></valueof2>
        </line>
    </xsl:template>
</xsl:stylesheet>

XML出力

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="myNS">
    <id>a</id>
    <lines>
        <line xmlns="">
            <valueof1>b</valueof1>
            <valueof2>c</valueof2>
        </line>
        <line xmlns="">
            <valueof1>d</valueof1>
            <valueof2>e</valueof2>
        </line>
        <line xmlns="">
            <valueof1>f</valueof1>
            <valueof2>g</valueof2>
        </line>
        <line xmlns="">
            <valueof1>h</valueof1>
            <valueof2>i</valueof2>
        </line>
    </lines>
</root>

XMLの期待される出力

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="myNS">
    <id>a</id>
    <lines>
        <line>
            <valueof1>b</valueof1>
            <valueof2>c</valueof2>
        </line>
        <line>
            <valueof1>d</valueof1>
            <valueof2>e</valueof2>
        </line>
        <line>
            <valueof1>f</valueof1>
            <valueof2>g</valueof2>
        </line>
        <line>
            <valueof1>h</valueof1>
            <valueof2>i</valueof2>
        </line>
    </lines>
</root>

注:この既存の投稿を見つけましたが、提案された解決策を適用する方法を理解できません:

4

1 に答える 1

2

xmlnsスタイルシートのリテラル結果要素は、スタイルシートのその時点でのスコープ内の宣言から名前空間を取得します。

    <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNS">
        <id><xsl:value-of select="id"/></id>
        <lines>
            <xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/>
        </lines>
    </root>

root要素とその接頭辞のないすべての子は名前myNS空間にあります。しかしで

<xsl:template match="db:row" mode="line">
    <line>
        <valueof1><xsl:value-of select="value1"/></valueof1>
        <valueof2><xsl:value-of select="value2"/></valueof2>
    </line>
</xsl:template>

スタイルシートのこの時点ではスコープにデフォルトがないため、要素linevalueofN要素は名前空間にありません。xmlns

したがって、簡単な答えは、テンプレートの要素xmlns="myNS"からトップレベルに移動することです。rootdb:rowxsl:stylesheet

<xsl:stylesheet version="2.0" 
    xmlns="myNS"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:db="http://www.sonicsw.com/esb/service/dbservice" 
    exclude-result-prefixes="db">
    <xsl:template match="/">
            <xsl:for-each-group select="//db:row" group-by="id">
                <xsl:sort select="id"/>
                    <xsl:apply-templates select="." mode="document"/>
            </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="db:row" mode="document">
        <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <id><xsl:value-of select="id"/></id>
            <lines>
                <xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/>
            </lines>
        </root>        
    </xsl:template>

    <xsl:template match="db:row" mode="line">
        <line>
            <valueof1><xsl:value-of select="value1"/></valueof1>
            <valueof2><xsl:value-of select="value2"/></valueof2>
        </line>
    </xsl:template>
</xsl:stylesheet>

rowただし、元のXMLの要素がすべて同じIDを持たない場合、root単一の親を持たない複数の要素を取得するため、このスタイルシートは整形式の出力を生成しないことに注意してください。match="/"出力が適切に形成されるように、テンプレートにラッピング要素を追加することをお勧めします。

PSを使用しているので、テンプレートを失い、そのコンテンツを直接feg内に移動してから、フィルターをかける代わりに使用するfor-each-group方が効率的かもしれません。mode="document"current-group[id=current()/id]

    <xsl:template match="/">
        <xsl:for-each-group select="//db:row" group-by="id">
            <xsl:sort select="current-grouping-key()"/>
            <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <id><xsl:value-of select="current-grouping-key()"/></id>
                <lines>
                   <xsl:apply-templates select="current-group()" mode="line"/>
                </lines>
            </root>        
        </xsl:for-each-group>
    </xsl:template>
于 2013-03-13T13:27:01.633 に答える