Kousaeng: Abfrage auf zwei xml Dokumenten beziehen

Hallo Leute,

irgenntwie steh ich grad total auf den Schlauch. Ich habe zwei xml Dokumente das eine heißt test.xml und hat folgende Struktur:
<root>
<person name="hans">
<haustier>nein</haustier>
</person>
<person name="august">
<haustier>nein</haustier>
</person>
...
</root>

und das andere blubb.xml sieht so aus:
<root>
<person name="hans">
<strasse>musterstrasse6</strasse>
</person>
<person name="hugo">
<strasse>musterallee23</strasse>
</person>
...
</root>

Ich Transformiere nun mit xsl die Daten von blubb.xml und möchte am Anfang eine Abfrage machen wenn die Person in test.xml vorkommt soll er dessen Daten nicht in das Zieldokument schreiben.

Also würde das Zieldokument in diesen Fall wie folgt aussehen:
<root>
<person name="hugo">
<strasse>musterallee23</strasse>
</person>
</root>

Aber irgenntwie bekomm ich das nicht so richtig hin. Mein Ansatz ist so:
<choose>
<xsl:when test="contains(document('test.xml')//person[@name],/root/person/@name)"/>
<otherwise>
<xsl:call-template name="format"/>
</otherwise>
</choose>

und im Template format habe ich dann die Regeln zum Formatieren drin.
Mein Problem ist jedoch dass die Abfrage nicht Funktioniert.

Kann mir da jemand weiter helfen, da ich schon langsam am verzweifeln bin.

Gruss Steffen

  1. Abgesehen, davon, dass ich hier eher eine for-each anweisung verwenden wurde, addressiert du unterschiedliche knoten, einmal das element und dann die attribute. schau mal ob es so geht:

    test="document('test.xml')//person[@name = current()/root/person/@name]"

    haengt allerdings davon ab, wo du dich gerade im blubb befindest. also muesstest du noch xptah anpassen

    test="document('test.xml')//person[@name = current()/ancestor::root/person/@name]"

    warum du hier contains verwendest weiss ich nicht aber muesste dann wohl so lauten

    test="document('test.xml')//person[contains(@name,current()/ancestor::root/person/@name])"

    Gruß, Holge r

    1. Abgesehen, davon, dass ich hier eher eine for-each anweisung verwenden wurde, addressiert du unterschiedliche knoten, einmal das element und dann die attribute. schau mal ob es so geht:

      Vielen Dank erstmal für deine schnelle Antwort,
      warum ich nicht for-each nehme geschieht aus dem grund, dass ich schon vorher eine for-each schleife bei der verarbeitung von blubb benutze:
      <xsl:for-each select="/root/person">
      <xsl:call-template name="format"/>
      </xsl:for-each>
      und im Template formate soll dann die abfrage, ob die person in test vorkommt, rein. Wenn nicht, soll er sich die daten aus blubb nehmen und in das zieldokument schreiben, wobei zu beachten ist, dass in blubb alle personen sind und in test nur ausgewählte.
      Wenn ich nun nochmal eine for-each nehme, so denke ich, geht mir die rechenzeit hoch oder täusche ich mich da?

      test="document('test.xml')//person[@name = current()/root/person/@name]"

      haengt allerdings davon ab, wo du dich gerade im blubb befindest. also muesstest du noch xptah anpassen

      wie beschrieben bin ich in /root/person

      test="document('test.xml')//person[@name = current()/ancestor::root/person/@name]"

      warum du hier contains verwendest weiss ich nicht aber muesste dann wohl so lauten

      contains hatte ich vorher, drin da ich anfangs alle @namen aus test in eine  variable schreiben wollte und dann abfragen wollte, wenn ich blubb verarbeite, ob der name in der variable steht. dies macht jedoch wenig sinn, so denk ich zumindest, oder? und daher würde ich schon dein oberes beispiel nehmen.

      test="document('test.xml')//person[contains(@name,current()/ancestor::root/person/@name])"

      Gruß, Holge r

      nach dem einbauen in meine xsl funktioniert es immer noch net, denn er gibt wieder mal nur ein leeres zieldokument aus :(. liegt es vieleicht an der for-each die das template für jede person aufruft?

      bin dankbar für jede anregung und kritik

      Grüße Steffen

      1. Hallo,

        Wie wäre es mal mit dem XSL?  (Ohne dem liegt das Problem eindeutig am Wetter.)

        Grüße
        Thomas

        1. so also so sieht die xsl jetzt aus:

          <?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" indent="yes"/>

          <xsl:template match="/">
                  <xsl:element name="Person">
                       <xsl:for-each select="/root/Person">
                           <xsl:call-template name="format"/>
                       </xsl:for-each>
                  </xsl:element>
              </xsl:template>

          <xsl:template name="format">
                      xsl:choose
                          <xsl:when test="document('test.xml')//Person[@name = current()/ancestor::person/@name]"/>
                          xsl:otherwise
                                 <xsl:call-template name="erstellung"/>
                          </xsl:otherwise>
                      </xsl:choose>
              </xsl:template>
              <xsl:template name="erstellung">
                  xsl:copy
                      <xsl:copy-of select="*"/>
                  </xsl:copy>
              </xsl:template>

          und er bringt mir nun alle personen im zieldokument, weil er, so denk ich mal, nicht kapiert was er in der when-bedingung machen soll

          Gruß Steffen

          1. Hallo,

            so also so sieht die xsl jetzt aus:

            Da sind schon mal eine Menge Fehler drinn, wenn ich dieses XSLT auf dein gepostetes XML beziehen. In den XMLs steht <person> im XSLT greifst du auf "/Person" zu.

            <?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" indent="yes"/>

            <xsl:template match="/">
                    <xsl:element name="Person">
                         <xsl:for-each select="/root/Person">

            <xsl:for-each select="root/person">

            (du bist bereits im "/" das ist also vor <root> nicht mehr nötig)

            <xsl:call-template name="format"/>
                         </xsl:for-each>
                    </xsl:element>
                </xsl:template>

            <xsl:template name="format">
                        xsl:choose
                            <xsl:when test="document('test.xml')//Person[@name = current()/ancestor::person/@name]"/>

            <xsl:when test="document('test.xml')/root/person[@name = current()/@name]"></xsl:when>

            Es ist kein guter Stil für when das "es soll nichts passieren" zu definieren. Dafür ist explizit otherwise gedacht, da der ja auch nur optional ist.

            xsl:otherwise
                                   <xsl:call-template name="erstellung"/>
                            </xsl:otherwise>
                        </xsl:choose>
                </xsl:template>
                <xsl:template name="erstellung">

            xsl:copy
                        <xsl:copy-of select="*"/>
                    </xsl:copy>

            Und was soll das bewirken? außer einer:
            <person>
                  <strasse>blablabla</strasse>
            </person>

            Wenn dann:
            <xsl:template name="erstellung">
              <xsl:copy-of select="."/>
             </xsl:template>

            ---------------------------

              
            <?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" indent="yes"/>  
              
             <xsl:template match="/">  
              <xsl:element name="Person">  
               <xsl:for-each select="root/person">  
                <xsl:call-template name="format"/>  
               </xsl:for-each>  
              </xsl:element>  
             </xsl:template>  
              
             <xsl:template name="format">  
              <xsl:choose>  
               <xsl:when test="document('person2.xml')/root/person[@name = current()/@name]">  
                <nix />  
               </xsl:when>  
               <xsl:otherwise>  
                <xsl:call-template name="erstellung"/>  
               </xsl:otherwise>  
              </xsl:choose>  
             </xsl:template>  
              
             <xsl:template name="erstellung">  
              <xsl:copy-of select="."/>  
             </xsl:template>  
            </xsl:stylesheet>  
            
            

            Ergebnis ausgehend von deinen XMLs

            <?xml version="1.0" encoding="UTF-8"?>
            <Person>
               <nix/>
               <person name="hugo">
                  <strasse>musterallee23</strasse>
               </person>
            </Person>

            Und eigentlich könnte man das ganze Gedönse noch etwas reduzieren:

              
            <?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" indent="yes"/>  
              
             <xsl:template match="/">  
              <xsl:element name="Person">  
               <xsl:for-each select="root/person[not(@name = document('person2.xml')/root//person/@name)]">  
                <xsl:copy-of select="."/>  
               </xsl:for-each>  
              </xsl:element>  
             </xsl:template>  
            </xsl:stylesheet>  
            
            

            Grüße
            Thomas

            1. Ja du hattest natürlich Recht, beim Zusammenfassen der xsl sind mir mehrere Fehler unterlaufen.

              Vielen Herzlichen Dank für deine Hilfe, jetzt Funktioniert es so wie gewollt und danke auch für deine Kritik, die werde ich zu Herzen nehmen.

              Viele Grüße

              Steffen