Thomas J.S.: Unerwünschte Elementknoten beim Kopieren

Beitrag lesen

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