2011-02-12 3 views
2

En utilisant XSLT, j'essaie de comprendre comment fusionner/mettre à jour les données dans un ensemble de noeuds avec des données d'un autre ensemble de noeuds. Les nœuds ont le même schéma, mais des parents différents. Les données doivent être fusionnées en fonction d'un attribut parent partagé. Dans l'exemple ci-dessous, les données sont copiées du principal au pilote. Est-ce que quelqu'un pourrait m'aider?Fusionner des données d'un noeud XML vers un autre noeud en utilisant XSLT

Entrée fichier:

<Info> 
    <Principal id="Insured"> 
    <PersonName> 
     <GivenName>Jane</GivenName> 
     <OtherGivenName>A</OtherGivenName> 
     <Surname>Doe</Surname> 
    </PersonName> 
    <PersonInfo> 
     <BirthDate>01-01-1980</BirthDate> 
     <MaritalStatus>M</MaritalStatus> 
    </PersonInfo> 
    <PrincipalInfo></PrincipalInfo> 
    </Principal> 
    <Policy> 
    <Driver id="Insured"> 
     <PersonName> 
     <GivenName>Jane</GivenName> 
     <Surname>Smith</Surname> 
     </PersonName> 
     <PersonInfo> 
     <BirthDate>01-01-1980</BirthDate> 
     <MaritalStatus>S</MaritalStatus> 
     <Occupation>Manager</Occupation> 
     </PersonInfo> 
    </Driver> 
    <PolicyInfo></PolicyInfo> 
    </Policy> 
</Info> 

Résultat souhaité:

<Info> 
    <Principal id="Insured"> 
    <PersonName> 
     <GivenName>Jane</GivenName> 
     <OtherGivenName>A</OtherGivenName> 
     <Surname>Doe</Surname> 
    </PersonName> 
    <PersonInfo> 
     <BirthDate>01-01-1980</BirthDate> 
     <MaritalStatus>M</MaritalStatus> 
    </PersonInfo> 
    <PrincipalInfo></PrincipalInfo> 
    </Principal> 
    <Policy> 
    <Driver id="Insured"> 
     <PersonName> 
     <GivenName>Jane</GivenName> 
     <OtherGivenName>A</OtherGivenName> 
     <Surname>Doe</Surname> 
     </PersonName> 
     <PersonInfo> 
     <BirthDate>01-01-1980</BirthDate> 
     <MaritalStatus>M</MaritalStatus> 
     <Occupation>Manager</Occupation> 
     </PersonInfo> 
    </Driver> 
    <PolicyInfo></PolicyInfo> 
    </Policy> 
</Info> 
+0

Est-ce une vraie affaire? Vous remplacez fondamentalement 'PersonName' par de nouvelles valeurs. Aucune fusion n'a lieu. – Flack

+0

Il peut y avoir des nœuds supplémentaires dans les sous-nœuds du pilote, que je veux quitter, donc le simple remplacement du nœud entier ne fonctionne pas. Notez le dans mon exemple. –

+0

En outre, le nœud de peut ne pas encore exister dans le , notez le . –

Répondre

2

Voici une solution complète:

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

<xsl:key name="kPrincipalById" match="Principal" 
    use="@id"/> 

<xsl:key name="kPrincipalChild" match="Principal/*/*" 
    use="concat(../../@id, name())"/> 

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

<xsl:template match="Driver/*"> 
    <xsl:variable name="vPrincipal" 
    select="key('kPrincipalById', ../@id)"/> 

    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <xsl:apply-templates select= 
    "$vPrincipal/*[name()=name(current())]/*"/> 
    <xsl:apply-templates select= 
    "*[not(key('kPrincipalChild', 
       concat(../../@id,name()) 
       ) 
      ) 
     ]"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

lorsque cette transformation est appliquée sur le document XML fourni :

<Info> 
    <Principal id="Insured"> 
     <PersonName> 
      <GivenName>Jane</GivenName> 
      <OtherGivenName>A</OtherGivenName> 
      <Surname>Doe</Surname> 
     </PersonName> 
     <PersonInfo> 
      <BirthDate>01-01-1980</BirthDate> 
      <MaritalStatus>M</MaritalStatus> 
     </PersonInfo> 
     <PrincipalInfo></PrincipalInfo> 
    </Principal> 
    <Policy> 
     <Driver id="Insured"> 
      <PersonName> 
       <GivenName>Jane</GivenName> 
       <Surname>Smith</Surname> 
      </PersonName> 
      <PersonInfo> 
       <BirthDate>01-01-1980</BirthDate> 
       <MaritalStatus>S</MaritalStatus> 
       <Occupation>Manager</Occupation> 
      </PersonInfo> 
     </Driver> 
     <PolicyInfo></PolicyInfo> 
    </Policy> 
</Info> 

le résultat recherché, correcte est produite:

<Info> 
    <Principal id="Insured"> 
     <PersonName> 
     <GivenName>Jane</GivenName> 
     <OtherGivenName>A</OtherGivenName> 
     <Surname>Doe</Surname> 
     </PersonName> 
     <PersonInfo> 
     <BirthDate>01-01-1980</BirthDate> 
     <MaritalStatus>M</MaritalStatus> 
     </PersonInfo> 
     <PrincipalInfo/> 
    </Principal> 
    <Policy> 
     <Driver id="Insured"> 
     <PersonName> 
      <GivenName>Jane</GivenName> 
      <OtherGivenName>A</OtherGivenName> 
      <Surname>Doe</Surname> 
     </PersonName> 
     <PersonInfo> 
      <BirthDate>01-01-1980</BirthDate> 
      <MaritalStatus>M</MaritalStatus> 
      <Occupation>Manager</Occupation> 
     </PersonInfo> 
     </Driver> 
     <PolicyInfo/> 
    </Policy> 
</Info> 

Explication:

  1. Les copies identity rule/modèles chaque nœud "en l'état" . L'utilisation et le remplacement de la règle d'identité est le modèle de conception XSLT le plus fondamental et le plus puissant.

  2. Il existe un seul modèle supplémentaire qui remplace la règle d'identité pour les éléments enfants de Driver. Il copie (et remplace effectivement les éléments grand-fils du même nom de Driver avec les éléments grand-enfant correspondants de Principal. Ensuite, il traite encore (copies) ces éléments petits-enfants de Driver qui ne disposent pas des éléments correspondants petits-enfants de Principal

  3. Pour accéder facilement aux Principal et ses petits-enfants - id et id ++ nom(), il y a deux keys défini et utilisé.

+0

Je suis nouveau sur XSLT et ne comprends toujours pas complètement votre solution, mais il semble fonctionner pour tous les tests que j'ai lancés. –

+0

+1 pour une réponse exhaustive. – Flack

+0

@ Tim-B: De rien. Pour mieux comprendre certains points clés de cette solution, veuillez en savoir plus sur le sujet de la "règle d'identité" et des clés xslt. J'ai édité ma réponse et maintenant l'explication a des liens vers ces deux sujets.Pour en savoir plus sur XSLT/XPath, vous pouvez utiliser les ressources identifiées dans cette réponse: http://stackoverflow.com/questions/339930/any-good-xslt-tutorial-book-blog-site-online/341589#341589 –

Questions connexes