2016-08-08 73 views
2

Ich habe Standard-Konfigurationselemente in einem XML-Dokument wie folgt:Wie können Elemente zwischen zwei Dokumenten mit XSLT 2.0 zusammengeführt werden?

<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> 

Spezifische Programme die Standardkonfiguration außer Kraft setzen können, zum Beispiel:

<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> 

Ich brauche die XML-Dokumente zusammenführen, so dass die Ausgabe wird:

Wenn das programmspezifische XML ein Element mit demselben Namen und übereinstimmenden Attributen wie das Standard-XML hat, t Wenn es den Wert im Ausgabedokument ersetzen soll.

Die XML ist ziemlich flach - es ist immer eine Reihe von Elementen unter dem Stammverzeichnis ProgramConfig mit keinen weiteren untergeordneten Elementen. Jedes Element definiert einen Dateisystempfad zu einem Asset.

Gibt es eine Möglichkeit, dies mit XSLT zu tun. Ich habe versucht, die Dokumentfunktion zu verwenden, aber ich bin nicht sicher, wie man mit einem Element und allen Attributen übereinstimmt.

Antwort

2

Mit XSLT 3.0 können Sie es lösen könnte for-each-group mit einer zusammengesetzten Gruppierung Schlüssel mit dem Knotennamen verwendet und alle Attribute:

<?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> 

Mit XSLT 2.0 es ein bisschen schwieriger ist, einzelne Gruppierungsschlüssel basierend zu konstruieren auf Name und alle Attributwerte:

<?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

Erstaunlich. Vielen Dank. Eine Frage - was bedeutet das 'as' Attribut von' node() * '? Ich war mir nicht sicher, wie es um Attribute geht, ich dachte, es würde nur mit Elementen übereinstimmen. – dave

+1

Gemäß https://www.w3.org/TR/xpath20/#id-sequencetype-syntax mit Sequenztypen, wie sie im 'as' Attribut verwendet werden, bedeutet" Any Art Test "' node() 'jede Art von Knoten und Attribute sind Knoten im Datenmodell. Es ist anders in einem XSLT-Muster, wo https://www.w3.org/TR/xslt20/#pattern-examples definiert "' node() 'entspricht einem anderen Knoten als einem Attributknoten, Namespace-Knoten oder Dokument-Knoten". –