Joe: Abfrage in einem externen XML-Dokument

Hallo,

ich möchte auf das Vorhandensein einer ID in einer zweiten (deklariert über die Variable 'import_data') XML-Datei prüfen. Falls diese ID vorliegt, dann soll sie in das erste XML übertragen werden. Falls diese ID nicht vorliegt, dann soll eine Hilfs-ID übertragen werden.
Die Hilfs-ID wird ebenfalls zum Matching der Datensätze benutzt.

Ich habe folgende choose-Anweisung erstellt:

xsl:choose
  <xsl:when test="$import_data/Import/Row/ID!=''">
    <xsl:attribute name="id">
      <xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/ID"/>
    </xsl:attribute>
  </xsl:when>
  xsl:otherwise
    <xsl:attribute name="id">
      <xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/hilfs_ID"/>
    </xsl:attribute>
  </xsl:otherwise>
</xsl:choose>

Die When-Anweisung wird durchgeführt und die entsprechende ID übertragen, die Otherwise-Anweisung jedoch nicht.

Kann mir jemand weiterhelfen?

Gruss Joe

  1. Hallo,

    ich möchte auf das Vorhandensein einer ID in einer zweiten (deklariert über die Variable 'import_data') XML-Datei prüfen. Falls diese ID vorliegt, dann soll sie in das erste XML übertragen werden. Falls diese ID nicht vorliegt, dann soll eine Hilfs-ID übertragen werden.
    Die Hilfs-ID wird ebenfalls zum Matching der Datensätze benutzt.

    Ich habe folgende choose-Anweisung erstellt:

    xsl:choose
      <xsl:when test="$import_data/Import/Row/ID!=''">
        <xsl:attribute name="id">
          <xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/ID"/>
        </xsl:attribute>
      </xsl:when>
      xsl:otherwise
        <xsl:attribute name="id">
          <xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/hilfs_ID"/>
        </xsl:attribute>
      </xsl:otherwise>
    </xsl:choose>

    Die When-Anweisung wird durchgeführt und die entsprechende ID übertragen, die Otherwise-Anweisung jedoch nicht.

    Kann mir jemand weiterhelfen?

    Da es in beiden Fällen ein Attribute erstellt wird, würde ich das etwas anders angehen:

    <xsl:attribute name="id">
       xsl:choose... </xsl:choose>
    </xsl:attribute>

    Dann solltest du dich davon überzeugen, dass "$import_data/Import/Row/ID" tatsächlich leer ist. Z.B.: normalize-space($import_data/Import/Row/ID) != ''

    Grüße
    Thomas

    1. Hallo,

      vielen Dank für die Tipps. Ich bekomme leider das gleiche Ergebnis, dass nur der erste Fall (Übertragung der ID) vorgenommen wird. Die otherwise-Anweisung wird komplett ignoriert.
      Auch dann, wenn ich die Abfrage umdrehe (auf eine leere ID prüfe) und dann die Hilfs-ID übertrage und als Alternative die reguläre ID. In diesem Fall wird nur die Hilfs-ID übertragen.

      Ich vermute den Fehler in der Prüfung bei xsl:when test="...", leider stehe ich noch total auf dem Schlauch und weiss nicht wo ich ansetzen kann.

      Gruss Joe

      1. Hallo,

        sorry, habe deine Antwort übersehen.

        vielen Dank für die Tipps. Ich bekomme leider das gleiche Ergebnis, dass nur der erste Fall (Übertragung der ID) vorgenommen wird. Die otherwise-Anweisung wird komplett ignoriert.
        Auch dann, wenn ich die Abfrage umdrehe (auf eine leere ID prüfe) und dann die Hilfs-ID übertrage und als Alternative die reguläre ID. In diesem Fall wird nur die Hilfs-ID übertragen.

        Ich vermute den Fehler in der Prüfung bei xsl:when test="...", leider stehe ich noch total auf dem Schlauch und weiss nicht wo ich ansetzen kann.

        Wo der Fehler liegen mag, kann ich dir nicht sagen, da ich nur das XSLT-Fragment von dir habe. Es wäre daher nützlich wenn du zumindest einen Teil von deinem XML zeigen würdest.

        Grüße
        Thomas

        1. Hallo,

          die XML-Dateien sind wie folgt aufgebaut:

          --> Ausgangsdatei, in die die IDs übertragen werden sollen; wobei das Attribut hilfs-id in der transformierten XML nicht mehr ausgegeben werden soll und ich somit bei der Transformation ignoriert habe.

          <volume>
           <chapter1>
            <chapter2>
             <region>
              <dataset hilfs-id ="Hilfs-ID_12_100" id="999098">
               <name>Dataset-Name1</name>
              </dataset>
              <dataset hilfs-id ="Hilfs-ID_12_101" id="">
               <name>Dataset-Name2</name>
              </dataset>
             </region>
            </chapter2>
           </chapter1>
          </volume>

          --> ID-Import-Datei (wurde aus einer CSV-Liste per Textimport im XMLSpy in eine XML-Datei gewandelt.)

          <Import>
           <Row>
            <hilfs_ID>Hilfs-ID_12_100</hilfs_ID>
            <name>Dataset-Name1</name>
            <ID>999098</ID>
           </Row>
           <Row>
            <hilfs_ID>Hilfs-ID_12_101</hilfs_ID>
            <name>Dataset-Name2</name>
            <ID/>
           </Row>
          </Import>

          Grüße Joe

          1. Hallo,

            die XML-Dateien sind wie folgt aufgebaut:

            --> Ausgangsdatei, in die die IDs übertragen werden sollen; wobei das Attribut hilfs-id in der transformierten XML nicht mehr ausgegeben werden soll und ich somit bei der Transformation ignoriert habe.

            <volume>
            <chapter1>
              <chapter2>
               <region>
                <dataset hilfs-id ="Hilfs-ID_12_100" id="999098">
                 <name>Dataset-Name1</name>
                </dataset>
                <dataset hilfs-id ="Hilfs-ID_12_101" id="">
                 <name>Dataset-Name2</name>
                </dataset>
               </region>
              </chapter2>
            </chapter1>
            </volume>

            --> ID-Import-Datei (wurde aus einer CSV-Liste per Textimport im XMLSpy in eine XML-Datei gewandelt.)

            <Import>
            <Row>
              <hilfs_ID>Hilfs-ID_12_100</hilfs_ID>
              <name>Dataset-Name1</name>
              <ID>999098</ID>
            </Row>
            <Row>
              <hilfs_ID>Hilfs-ID_12_101</hilfs_ID>
              <name>Dataset-Name2</name>
              <ID/>
            </Row>
            </Import>

            ich kenne jetzt nicht den Rest deines XSLs, aber das grundsätzliche Problem bei:

            <xsl:choose>  
              <xsl:when test="$import_data/Import/Row/ID!=''">  
                <xsl:attribute name="id">  
                  <xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/ID"/>  
                </xsl:attribute>  
              </xsl:when>  
              <xsl:otherwise>  
                <xsl:attribute name="id">  
                  <xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/hilfs_ID"/>  
                </xsl:attribute>  
              </xsl:otherwise>  
            
            

            ist, dass "$import_data/Import/Row/ID" das immer erste Row im import XML nimmt. Dadurch stimmt der Vergleich wohl nie.
            Falls du xsl:choose in einem xsl:for-each verwendest, könnte das anderes aussehen, aber wie gesagt: ich kenne den rest deines XSLs nicht.

            Wie sieht also die Umgebung von deinem xsl:choose aus?

            Solle das keine Rolle spielen, dann kannst du so etwas verwenden:

              
            <xsl:attribute name="id">  
            				<xsl:choose>  
            					<xsl:when test="not(@id = '')">  
            						<xsl:value-of select="$import_data//*[hilfs_ID = $hilfs-id]/ID"/>  
            					</xsl:when>  
            					<xsl:otherwise>  
            						<xsl:value-of select="$import_data//*[hilfs_ID = $hilfs-id]/hilfs_ID"/>  
            					</xsl:otherwise>  
            				</xsl:choose>  
            			</xsl:attribute>  
            
            

            und noch einfacher wäre eigentlich:

              
            <xsl:attribute name="id">  
            				<xsl:choose>  
            					<xsl:when test="@id = ''">  
            						<xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/hilfs_ID"/>  
            					</xsl:when>  
            					<xsl:otherwise>  
            						<xsl:value-of select="@id"/>  
            					</xsl:otherwise>  
            				</xsl:choose>  
            			</xsl:attribute>  
            
            

            Beide würden das ergebnis liefern:
            <dataset id="999098"/>
            <dataset id="Hilfs-ID_12_101"/>

            Grüße
            Thomas

            1. Hallo,

              nachfolgend das gesamte XSL. Das nur das erste Row-Element übernommen wird, ist nicht das Problem, denn wenn eine ID vorhanden ist, dann wird diese auch korrekt für alle Datensätze übergeben. Es fehlt eben nur die Hilfs-ID, falls die reguläre ID nicht vorhanden ist.
              Deine beiden Vorschläge haben leider nur für den regulären Fall (das die ID übertragen wird) zum Erfolg geführt.

              Vor dem Übertragen der ID werden noch weitere Elemente und Attribute übertragen. Dies funktioniert jedoch ohne Probleme und ich habe diese in der XSL weggelassen.

              <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
              <xsl:output method="xml" media-type="text/xml" version="1.0" encoding="UTF-8" indent="yes"/>

              <xsl:strip-space elements="*" />

              <xsl:variable name="Import\_FileName">  
              	<xsl:text>Import\_files/Import-file.xml</xsl:text>  
              </xsl:variable>	  
              
              <xsl:variable name="import\_data" select="document($Import\_FileName)" />  
                
              <xsl:variable name="newline">  
              	<xsl:text>&#xA;</xsl:text>  
              </xsl:variable>  
              
              <xsl:template match="/">  
              	<xsl:value-of select="$newline" />  
              		<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE volume SYSTEM "mpallg.dtd">]]></xsl:text>  
              	<xsl:value-of select="$newline" />  
              	<xsl:apply-templates select="node()"/>  
              </xsl:template>	  
              
              <xsl:template match="node()|@\*">  
              	<xsl:copy>  
              		<xsl:apply-templates select="@\*|node()" />  
              	</xsl:copy>  
              </xsl:template>	  
              
              
              <xsl:template match="dataset">  
              
              	<xsl:variable name="hilfs\_id" select="@hilfs\_id" />  
              
              		<xsl:element name="dataset">  
              		  
              		<!-- Übertragen anderer Attribute und Elemente -->  
              		  
              			<xsl:attribute name="id">  
              				<xsl:choose>  
              					<xsl:when test="not(@id = '')">  
              							<xsl:value-of select="$import\_data//\*[hilfs\_ID = $hilfs\_id]/ID"/>  
              					</xsl:when>  
              					<xsl:otherwise>			  
              							<xsl:value-of select="$import\_data//\*[hilfs\_ID = $hilfs\_id]/hilfs\_ID"/>  
              					</xsl:otherwise>  
              				</xsl:choose>  
              			</xsl:attribute>  
              			  
              		<!-- Übertragen anderer Attribute und Elemente -->  
              		  
              		</xsl:element>  
                
              </xsl:template>		  
              

              </xsl:stylesheet>

              Grüße Joe

              1. Hallo,

                nachfolgend das gesamte XSL. Das nur das erste Row-Element übernommen wird, ist nicht das Problem, denn wenn eine ID vorhanden ist, dann wird diese auch korrekt für alle Datensätze übergeben. Es fehlt eben nur die Hilfs-ID, falls die reguläre ID nicht vorhanden ist.
                Deine beiden Vorschläge haben leider nur für den regulären Fall (das die ID übertragen wird) zum Erfolg geführt.

                Ich kann das nicht nachvollziehen.
                Ich habe mit dem zwei XML-Dateien die du gepostet hast einen Text gemacht.

                Vor dem Übertragen der ID werden noch weitere Elemente und Attribute übertragen. Dies funktioniert jedoch ohne Probleme und ich habe diese in der XSL weggelassen.

                  <xsl:variable name="hilfs\_id" select="@hilfs\_id" />  
                

                Das Attribut in deinem XML heisst nicht hilfs_id (mit Unterstrich) sondern hilfs-id (mit Bindestrich)

                Wenn ich das XSL was du gepostet hast mit dieser Korrektur verwende:

                  
                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
                	<xsl:output method="xml" media-type="text/xml" version="1.0" encoding="UTF-8" indent="yes"/>  
                	  
                	<xsl:strip-space elements="*" />  
                	<xsl:variable name="Import_FileName">  
                		<xsl:text>importID2.xml</xsl:text>  
                	</xsl:variable>  
                	  
                	<xsl:variable name="import_data" select="document($Import_FileName)" />  
                	  
                	<xsl:variable name="newline">  
                		<xsl:text>&#xA;</xsl:text>  
                	</xsl:variable>  
                	  
                	<xsl:template match="/">  
                		<xsl:value-of select="$newline" />  
                		<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE volume SYSTEM "mpallg.dtd">]]></xsl:text>  
                		<xsl:value-of select="$newline" />  
                		<xsl:apply-templates select="node()"/>  
                	</xsl:template>  
                	  
                	<xsl:template match="node()|@*">  
                		<xsl:copy>  
                			<xsl:apply-templates select="@*|node()" />  
                		</xsl:copy>  
                	</xsl:template>  
                	  
                	  
                	<xsl:template match="dataset">  
                		<xsl:variable name="hilfs_id" select="@hilfs-id" />  
                		<xsl:element name="dataset">  
                			  
                			<!-- Übertragen anderer Attribute und Elemente -->  
                			  
                			<xsl:attribute name="id">  
                				<xsl:choose>  
                					<xsl:when test="not(@id = '')">  
                						<xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/ID"/>  
                					</xsl:when>  
                					<xsl:otherwise>  
                						<xsl:value-of select="$import_data//*[hilfs_ID = $hilfs_id]/hilfs_ID"/>  
                					</xsl:otherwise>  
                				</xsl:choose>  
                			</xsl:attribute>  
                			  
                			<!-- Übertragen anderer Attribute und Elemente -->	  
                		</xsl:element>  
                	</xsl:template>  
                </xsl:stylesheet>  
                
                

                bekomme ich folgende korrekte Ausgabe:

                  
                <?xml version="1.0" encoding="UTF-8"?>  
                <!DOCTYPE volume SYSTEM "mpallg.dtd">  
                <volume>  
                   <chapter1>  
                      <chapter2>  
                         <region>  
                            <dataset id="999098"/>  
                            <dataset id="Hilfs-ID_12_101"/>  
                         </region>  
                      </chapter2>  
                   </chapter1>  
                </volume>  
                
                

                Grüße
                Thomas

                1. Hallo,

                  danke für Deine Hilfe. Die Benennung mit Bindestrich bzw. Unterstrich war ein Kopierfehler, in der XSL ist es korrekt.

                  Irgendwie komme ich mit diesen XSL-Varianten nicht weiter. Ich probier da nochmal weiter.

                  Danke nochmal.
                  Gruss Joe