2016-08-08 7 views
2

次のように私は、XML文書内のデフォルト設定項目があります。XSLT 2.0を使用して2つのドキュメント間で要素をマージする方法は?

<ProgramConfig> 

    <Fragment xml:lang="en" name="TargetSector">fragment/target_sector.xdp</Fragment> 
    <Fragment xml:lang="fr" name="TargetSector">fragment/target_sector_fr.xdp</Fragment> 


    <MasterTemplate xml:lang="en">master/default_en.xdp</MasterTemplate> 
    <MasterTemplate xml:lang="fr">master/default_fr.xdp</MasterTemplate> 

</ProgramConfig> 

特定のプログラムには、例えば、デフォルトの設定を上書きすることができます。

<ProgramConfig> 

    <Fragment xml:lang="en" name="TargetSector">fragment/1-5ABQ/target_sector.xdp</Fragment> 

    <MasterTemplate xml:lang="fr">master/default_fr_1-5ABQ.xdp</MasterTemplate> 

</ProgramConfig> 

をするように私は、XML文書をマージする必要があります

プログラム固有のXMLに、デフォルトのXMLと同じ名前と一致する属性を持つ要素がある場合、tそれは出力文書の値を置き換える必要があります。

XMLはかなりフラットです。これは、ProgramConfigルートの下にある要素のセットであり、それ以上の子要素はありません。各要素は、アセットへのファイルシステムパスを定義します。

XSLTを使用してこれを行う方法はありますか?私はドキュメント関数を使ってみましたが、要素とすべての属性とのマッチング方法がわかりません。あなたはノード名とすべての属性を使用して複合グループ化キーでfor-each-groupを使用して、それを解決する可能性がXSLT 3.0を使用して

答えて

2

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

    <xsl:output indent="yes"/> 

    <xsl:template name="xsl:initial-template"> 
     <ProgramConfig> 
      <xsl:for-each-group select="doc('defaultConfig.xml')/ProgramConfig/*, 
             doc('overrideConfig.xml')/ProgramConfig/*" 
             group-by="node-name(.), sort(@*, function($a) { name($a) })" composite="yes"> 
       <xsl:copy-of select="if (current-group()[2]) then current-group()[2] else current-group()[1]"/> 
      </xsl:for-each-group> 
     </ProgramConfig> 
    </xsl:template> 

</xsl:stylesheet> 

XSLT 2.0とそれがベースの単一のグループ化キーを構築するために少しより困難です名前とすべての属性値:

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

    <xsl:output indent="yes"/> 

    <xsl:function name="mf:sort" as="node()*"> 
     <xsl:param name="input-nodes" as="node()*"/> 
     <xsl:perform-sort select="$input-nodes"> 
      <xsl:sort select="name()"/> 
     </xsl:perform-sort> 
    </xsl:function> 

    <xsl:template name="main"> 
     <ProgramConfig> 
      <xsl:for-each-group select="doc('defaultConfig.xml')/ProgramConfig/*, 
       doc('overrideConfig.xml')/ProgramConfig/*" 
       group-by="string-join((string(node-name(.)), mf:sort(@*)), '|')"> 
       <xsl:copy-of select="if (current-group()[2]) then current-group()[2] else current-group()[1]"/> 
      </xsl:for-each-group> 
     </ProgramConfig> 
    </xsl:template> 

</xsl:stylesheet> 
+0

素晴らしい。ありがとうございました。 1つの質問 - 'node()*'の 'as'属性はどういう意味ですか?私はどのようにそれが属性にマッチしているかわからなかった、私はそれが要素だけと一致すると思った。 – dave

+1

'as'属性で使用されているようなシーケンス型のhttps://www.w3.org/TR/xpath20/#id-sequencetype-syntaxによると、「任意の種類のテスト」' node() 'はどんな種類のノード属性はデータモデル内のノードです。その違いは、https://www.w3.org/TR/xslt20/#pattern-examplesで "node()"が属性ノード、名前空間ノード、または文書ノード以外のノードと一致するXSLTパターンです。 –

関連する問題