2012-03-28 7 views
0

Hoffe, dass du die Hilfe eines Gurus findest, um das nächste Problem herauszufinden.XSLT Gouping, für jede und betroffene Schleife. Wie duplikate eliminieren?

Ich habe zwei XML-Dateien. Firts hier ein (text.xml):

<text> 
<ref>Author1, Title1, Date1</ref> 
<ref>Author75, Title75, Date2</ref> 
<ref>Author2, Title2, Date2</ref> 
<ref>Author3, Title3, Date3</ref> 
<text> 

und die zweite so (list.xml):

<list> 
<bibl xml:id="1"><author>Author1</author><date>Date1</date></bibl> 
<bibl xml:id="2"><author>Author2</author><date>Date2</date></bibl> 
<bibl xml:id="3"><author>Author3</author><date>Date3</date></bibl> 
</list> 

I text.xml und die Prüfung abfragen möchten gegen list.xml hinzufügen @xml: id (von list.xml) bis <ref> (von text.xml) wic h enthält den gleichen Autor und das gleiche Datum. Wenn nicht, dann kopieren Sie das Original <ref>.

Deshalb möchte ich erhalten:

<ref xml:id="1">Author1, Title1, Date1</ref> 
<ref>Author75, Title75, Date2</ref> 
<ref xml:id="2>Author2, Title2, Date2</ref> 
etc. 

Mein XSLT zu identifizieren und alle correpondence:

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

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

    <xsl:template match="ref"> 
     <xsl:variable name="ref" select="."/> 
     <xsl:for-each select="document('list.xml')//bibl"> 
      <xsl:variable name="bibl" select="."/> 
      <xsl:variable name="author" select="author"/> 
      <xsl:variable name="date" select="date"/> 
      <xsl:choose> 
       <xsl:when test="contains($ref, $author) and contains($ref, $date)"> 
        <ref> 
         <xsl:attribute name="xml:id"> 
          <xsl:value-of select="$bibl/@xml:id"/> 
         </xsl:attribute> 
         <xsl:value-of select="$ref"/> 
        </ref> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:copy-of select="$ref"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Aber dann gibt es nicht correpondence es ist nicht nur richtig <ref> kopieren, sondern kopieren Alle <ref> die Anzahl der Zeit, die ich habe <bibl> Knoten in der zweiten Datei.

So Problem ist in <xsl:otherwise><xsl:copy-of select="$ref"/></xsl:otherwise>. Irgendwelche Ideen, wie ich nur diesen eindeutigen Wert erreichen kann, den ich brauche? Ich weiß, dass es tatsächlich sehr einfach sein muss, und ich probiere key, generate-id, für jede Gruppe, distinct-values, kann es aber nicht herausfinden.

Antwort

0

Das Problem ist, dass man für jede Iteration der for-jede Schleife einref Element schaffen, ob es eine Übereinstimmung gibt oder nicht.

Was müssen Sie in diesem Fall zu tun ist, um den ref Elemente erstellen außerhalb der for-each und dann nur das id-Attribut für das Element innerhalb der Schleife Anpassung schaffen

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ref"> 
     <xsl:variable name="ref" select="."/> 
     <ref> 
     <xsl:apply-templates select="@* "/> 
     <xsl:for-each select="document('list.xml')//bibl"> 
      <xsl:variable name="bibl" select="."/> 
      <xsl:variable name="author" select="author"/> 
      <xsl:variable name="date" select="date"/> 
      <xsl:choose> 
       <xsl:when test="contains($ref, $author) and contains($ref, $date)"> 
        <xsl:attribute name="xml:id"> 
        <xsl:value-of select="$bibl/@xml:id"/> 
        </xsl:attribute> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
     <xsl:apply-templates select="node()"/> 
     </ref> 
    </xsl:template> 
</xsl:stylesheet> 

Bei der Anwendung Ihr Beispiel XML, wird die folgende Ausgabe

<text> 
    <ref xml:id="1">Author1, Title1, Date1</ref> 
    <ref>Author75, Title75, Date2</ref> 
    <ref xml:id="2">Author2, Title2, Date2</ref> 
    <ref xml:id="3">Author3, Title3, Date3</ref> 
</text> 

jedoch Ihre aktuelle Methode nicht sehr effizient ist, wie für jeden ref Element die Sie iterieren alle bibl Elemente. Ein anderer Ansatz wäre, den Autor und Datum aus den Elementen ref zu extrahieren und dann das bibl Element nachschlagen direkt

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ref"> 
     <xsl:variable name="author" select="normalize-space(substring-before(., ','))"/> 
     <xsl:variable name="date" select="normalize-space(substring-after(substring-after(., ','), ','))"/> 
     <ref> 
     <xsl:apply-templates select="@* "/> 
     <xsl:apply-templates select="document('list.xml')//bibl[author=$author][date=$date]"/> 
     <xsl:apply-templates select="node()"/> 
     </ref> 
    </xsl:template> 

    <xsl:template match="bibl"> 
     <xsl:attribute name="xml:id"> 
     <xsl:value-of select="@xml:id"/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

Dies sollte auch die gleichen Ergebnisse liefern.

+0

Vielen Dank! Es funktioniert perfekt! Völlig einverstanden, dass Ihre zweite Lösung viel eleganter und effizienter ist. Aber eigentlich erste XML-Datei (** text.xml **) ist nur ein Beispiel. Die echte '' es ist etwas wie ' J. Smith, Buchtitel, Verlag, 2001, S.211' oder ' Buchtitel, eds. Smith John., 2005 ', usw. Also ich nicht wirklich jetzt, wo ich Autor oder Datum finden kann, alles weiß ich, dass es irgendwo hier ist. Nochmals vielen Dank! –

0

EDIT: humm ... zu viel Fokus auf xsl Syntax, ich, dass früher gesehen haben sollte ... Sie haben eine Verbindung gebracht äußere Schleife über jede ref und eine innere Schleife über jede bibl. Sie generieren ein Element für jede bibl für jede ref unabhängig von Übereinstimmung oder keine Übereinstimmung. Also, anstelle der xsl:otherwise brauchen Sie einen Haken nach der for-each Schleife, um zu sehen, ob es keine Übereinstimmung gab und tun Sie die copy-of wenn notwendig.

nicht sicher, wie die Prüfung zu tun, though..maybe mit position() und count() der erzeugten <ref> s, sorry ... hat keine Zeit mehr jetzt über dieses Recht zu denken.

nicht wirklich eine Erklärung, aber eine Behelfslösung:

<xsl:otherwise> 
    <ref> 
     <xsl:value-of select="$ref"/> 
    </ref> 
</xsl:otherwise> 

Meine Vermutung ist, dass das Problem in $ ref liegt, die in diesem Moment kein XPath-Ausdruck ist (wenn ich xsl-t richtig erinnere )

+0

Vielen Dank für Antwort, aber immer noch ein Vielfaches Duplikat aller . Ich denke, es ist am meisten ein Problem der eindeutigen ID jedes $ ref. –

+0

Ja, es ist genau mein Problem, Sie unterscheiden es sehr gut. Ich versuchte noch mit contains() und nicht (enthält()) anstelle aber immer noch das gleiche Problem haben. Wie auch immer, danke für deine Zeit. –