2016-10-07 20 views
1

に基づいて一致して要素を置き換える:XSLTは、私は、次のソースXML文書を持っている子ノードの値

<UserDefinedFields> 
    <UserDefinedField> 
    <Name>ABC</Name> 
    <Value>123</Value> 
    </UserDefinedField> 
    <UserDefinedField> 
    <Name>XYZ</Name> 
    <Value>645q3245</Value> 
    </UserDefinedField> 
</UserDefinedFields> 

私は一致<Name>値がある場合は、入力XMLから一致するノードを上書きしたい...だから、他に言葉、でこれをマージの最終結果:

<UserDefinedField> 
    <Name>XYZ</Name> 
    <Value>NEWVALUE!</Value> 
</UserDefinedField> 

は...次のようになります。

<UserDefinedFields> 
    <UserDefinedField> 
    <Name>ABC</Name> 
    <Value>123</Value> 
    </UserDefinedField> 
    <UserDefinedField> 
    <Name>XYZ</Name> 
    <Value>NEWVALUE!</Value> 
    </UserDefinedField> 
</UserDefinedFields> 

これを達成するための適切なXSLT変換は何ですか?

XSLT 2.0または1.0の回答は問題ありません。あなたがグループ化でこれを行うことができ

答えて

1

<xsl:for-each-group 
    select="$doc1//UserDefinedField, $doc2//UserDefinedField" 
    group-by="Name"> 
    <xsl:copy-of select="current-group()[last()]"/> 
</xsl:for-each-group> 
+0

Dr. Kay、提案されたソリューションは '$ doc1 // UserDefinedField'要素と一致しない' $ doc2 // UserDefinedField'要素を出力すると私の理解は間違っていますか?もしそうなら、これはOPが望んでいるものではありません - '$ doc1'の要素にマッチ("オーバーライド ")する' $ doc2 // UserDefinedField'要素だけを出力したい –

+1

OPの要件が由来しますが、私の解決策では、doc2のエントリがdoc1のエントリと一致しない場合、doc2のエントリが出力に追加されることを前提としています。それが欲しいものではない場合は、 'if(current-group()[1] /(/)は$ doc1)のようなもので解決策を調整することができます... ' –

+0

Dr. Kay、Re:" フラグ OPの要件の読者がどこから来ているのか分かりません。それはちょうど私の読書ではありません - それは正確に質問で指定されています: "一致する値があれば入力XMLから一致するノードを上書きしたい.." * * *をメモしてください... –

0

は、あなたが「初期」のXML文書を処理するために、あなたのプロセッサに指示し、パラメータとして「上書き」のドキュメントへのパスを供給していると仮定すると、あなたが行うことができます:

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:param name="path-to-update">update.xml</xsl:param> 
<xsl:key name="fld" match="UserDefinedField" use="Name" /> 

<!-- identity transform --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Value"> 
    <xsl:variable name="update" select="key('fld', ../Name, document($path-to-update))" /> 
    <xsl:copy> 
     <xsl:value-of select="if ($update) then $update/Value else ."/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
0

ちょうど私をオーバーライドするために、このテンプレートを使用しますdentityルール:ここ

<xsl:template match="UserDefinedField[key('kFieldByName', Name, $vDoc2)]/Value/text()"> 
    <xsl:value-of select="key('kFieldByName', ../../Name, $vDoc2)[1]"/> 
    </xsl:template> 

Iは、第2の文書は、文書要素(先頭の要素)を有し、異なる深さで多くのUserDefinedField要素を含むことができると仮定する。便宜上、2番目の文書は変換でインライン展開されています。実際の場合はdoc()関数を使用できます。私は<xsl:key>を宣言して、Nameの子の値UserDefinedFieldを2番目の文書で使って効率的に新しい値を見つけることを宣言します。ここで

は完全な変換です:指名手配、正しい結果がを生産している

<UserDefinedFields> 
    <UserDefinedField> 
    <Name>ABC</Name> 
    <Value>123</Value> 
    </UserDefinedField> 
    <UserDefinedField> 
    <Name>XYZ</Name> 
    <Value>645q3245</Value> 
    </UserDefinedField> 
</UserDefinedFields> 

この変換が提供されるXML文書に適用され

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="kFieldByName" match="Value" use="../Name"/> 

<xsl:variable name="vDoc2"> 
    <patterns> 
    <UserDefinedField> 
     <Name>XYZ</Name> 
     <Value>NEWVALUE!</Value> 
     </UserDefinedField> 
    </patterns> 
</xsl:variable> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="UserDefinedField[key('kFieldByName', Name, $vDoc2)]/Value/text()"> 
    <xsl:value-of select="key('kFieldByName', ../../Name, $vDoc2)[1]"/> 
    </xsl:template> 
</xsl:stylesheet> 

<UserDefinedFields> <UserDefinedField> <Name>ABC</Name> <Value>123</Value> </UserDefinedField> <UserDefinedField> <Name>XYZ</Name> <Value>NEWVALUE!</Value> </UserDefinedField> </UserDefinedFields> 
関連する問題