Andreas: Unerwünschte Elementknoten beim Kopieren

Hallo ( spzieller Gruss an Thomas ;-) )

Ich möchte zwei XML Dokumente vergleichen und die fehlenden Werte vom anderen übernehmen. Leider habe ich Probleme mit dem Iterieren. Die Ergebnisknoten kommen leider mehrfach vor

Rauskommen soll folgendes :

<mitarbeiter id="4">
<nachname>Huber</nachname>
<info rating="ok" info-id="338">

<!-->aus dem zweiten XML Dokument übernommen<!-->
<vertrag nr="1">Verhandlung</vertrag>

<telefon>5524</telefon>
    <info rating="sehr gut" gewicht="95" grösse="1.84" statur="kräftig"/>
   </mitarbeiter>

usw....

Hier das Beispiel :

Quelldatei :

<?xml version="1.0" encoding="UTF-8"?>
<mb-datenbank>
 <abteilung>
  <name>
        IT-Abteilung
    </name>
  <angehoerige>
   <mitarbeiter id="5">
    <nachname>Meier</nachname>
    <info rating="gut" info-id="334">
     <vertrag>2 Jahre</vertrag>
    </info>
    <telefon>3421</telefon>
    <info rating="gut" gewicht="80" grösse="1.85" statur="normal"/>
   </mitarbeiter>
   <mitarbeiter id="4">
    <nachname>Huber
                   </nachname>
    <info rating="ok" info-id="338">
     </info>
    <telefon>5524</telefon>
    <info rating="sehr gut" gewicht="95" grösse="1.84" statur="kräftig"/>
   </mitarbeiter>
   <mitarbeiter id="7">
    <nachname>Hinkelstein</nachname>
    <info rating="ok" info-id="355">
   </info>
    <telefon>3456</telefon>
    <info rating="ok" gewicht="73" grösse="1.88" statur="schlank"/>
   </mitarbeiter>
   <mitarbeiter id="9">
    <nachname>Krause</nachname>
    <info rating="mangelhaft" info-id="364">>
    </info>
    <telefon>4556</telefon>
    <info rating="schlecht" gewicht="97" grösse="1.73" statur="stark untersetzt"/>
   </mitarbeiter>
  </angehoerige>
 </abteilung>
</mb-datenbank>

*******************************************

Hier das zweite XML Dokument, von welchem die jeweiligen Vertragsknoten kopiert wird :

Name des Dokuments : test1.xml

<?xml version="1.0" encoding="UTF-8"?>
<mb-datenbank>
 <abteilung>
  <name>
   Produktion
    </name>
  <angehoerige>
   <mitarbeiter id="5">
    <nachname>Winther</nachname>
    <info rating="gut" info-id="334">
     <vertrag>2 Jahre</vertrag>
    </info>
    <telefon>3421</telefon>
    <info rating="gut" gewicht="80" grösse="1.85" statur="normal"/>
   </mitarbeiter>
   <mitarbeiter id="4">
    <nachname>Heinz</nachname>
    <info rating="ok" info-id="338">
     <vertrag nr="1">Verhandlung</vertrag>
    </info>
    <telefon>5524</telefon>
    <info rating=" gut" gewicht="86" grösse="1.83" statur="normal"/>
   </mitarbeiter>
   <mitarbeiter id="7">
    <nachname>Kruse</nachname>
    <info rating="ok" info-id="355">
     <vertrag nr="2">Verhandlung</vertrag>
    </info>
    <telefon>3456</telefon>
    <info rating="ok" gewicht="125" grösse="1.88" statur="Bierbauch"/>
   </mitarbeiter>
   <mitarbeiter id="9">
    <nachname>Berger</nachname>
    <info rating="mangelhaft" info-id="364">
     <vertrag nr="3">Verhandlung</vertrag>
    </info>
    <telefon>4556</telefon>
    <info rating="ok" gewicht="73" grösse="1.83" statur="normal"/>
   </mitarbeiter>
  </angehoerige>
 </abteilung>
</mb-datenbank>

*************************************

Das XSL Stylesheet :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml"/>
 <xsl:template match="@*|node()">
  xsl:copy
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="//info[@info-id]">
  xsl:copy
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
  <xsl:if test="not(vertrag)">
   <xsl:apply-templates select="document('test1.xml')//info[@info-id]/vertrag" mode="copy"/>
  </xsl:if>
 </xsl:template>
 <xsl:template match="@*|node()" mode="copy">
  xsl:copy
   <xsl:copy-of select="@*|node()"/>
   <xsl:apply-templates mode="copy"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

  1. Hallo,

    Hallo ( spzieller Gruss an Thomas ;-) )

    An welchen denn? ;-)

    Ich möchte zwei XML Dokumente vergleichen und die fehlenden Werte vom anderen übernehmen. Leider habe ich Probleme mit dem Iterieren. Die Ergebnisknoten kommen leider mehrfach vor

    Rauskommen soll folgendes :
    <!-->aus dem zweiten XML Dokument übernommen<!-->
    <vertrag nr="1">Verhandlung</vertrag>

    Hier das Beispiel :

    Quelldatei :

    <?xml version="1.0" encoding="UTF-8"?>
        <info rating="sehr gut" gewicht="95" grösse="1.84" statur="kräftig"/>

    Ich würde davon abraten Umlaute im Attributnamen zu verwenden.
    Außerdem verdient dieses XML nicht die Bezeichnung XML. Sinnlose Ansammlung von Elementen die keinen Zusammehang aufweisen: nimm das <info>, vollkommen unterschiedliche Verwendung mit unterschiedlichen Attributen. Aber egal, ist nur meine Meinung.

    »»Leider habe ich Probleme mit dem Iterieren. Die Ergebnisknoten kommen leider mehrfach vor

    Das XSL Stylesheet :

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <xsl:template match="@*|node()">
      xsl:copy
       <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
    <xsl:template match="//info[@info-id]">
      xsl:copy
       <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
      <xsl:if test="not(vertrag)">
       <xsl:apply-templates select="document('test1.xml')//info[@info-id]/vertrag" mode="copy"/>
      </xsl:if>
    </xsl:template>
    <xsl:template match="@*|node()" mode="copy">
      xsl:copy
       <xsl:copy-of select="@*|node()"/>
       <xsl:apply-templates mode="copy"/>
      </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

    Du scheinst Thomas' Votschlag aus https://forum.selfhtml.org/?t=114035&m=725695 mit meinem aus https://forum.selfhtml.org/?t=113936&m=724947 zu kombinieren.

    <xsl:template match="//info[@info-id]">
      xsl:copy
       <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
      <xsl:if test="not(vertrag)">
       <xsl:apply-templates select="document('test1.xml')//info[@info-id]/vertrag" mode="copy"/>
      </xsl:if>
     </xsl:template>

    Das // ist unnötig.
    Die if-Abfrage sollte im <copy> drinn stehen, sonst wird <vertag> nach <info> ausgegeben und nicht als dessen Unterlement.
    "select="document('test1.xml')//info[@info-id]/vertrag" wird auf irgendeiner <info> mit @info-id zutrreffen, (meistens auf das erste wo es vorkommt), aber nicht unbedingt auf dem <info> was du brauchst.
    Auf mode="copy" kannst du in diesem Fall verzeichten, du hast bereits ein Template für alles: <xsl:template match="@*|node()">

    Und so sollte dein XSL aussehen:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="xml" />

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

    <xsl:template match="info[@info-id]">
      <xsl:variable name="currentid" select="@info-id" />
      xsl:copy
       <xsl:apply-templates select="@*|node()"/>
       <xsl:if test="not(vertrag)">
        <xsl:apply-templates select="document('test1.xml')//info[@info-id = $currentid]/vertrag" />
       </xsl:if>
      </xsl:copy>
     </xsl:template>
    </xsl:stylesheet>

    Grüße
    Thomas