2017-02-09 1 views
0

Ich bin ein xsl Anfänger und ich habe versucht, dies für ein paar Tage zu arbeiten, aber ich habe einige Probleme. Ich habe ein paar Nachforschungen angestellt und ein paar verschiedene Lösungen ausprobiert, aber ich finde es nicht richtig. Mit xsl 1.0 und einer angegebenen Eingabe muss ich Duplikate entfernen und auch nach bestimmten Schlüsselwörtern filtern können.Wie Duplikate entfernen und nach bestimmten Inhalten in XSL filtern?

Hier ist der Eingang:

<vce> 
<document> 
    <content name="title">X</content> 
    <content name="description"> 
     <content name="h3">A</content> 
     <content name="h3">B</content> 
     <content name="h3">C</content> 
     <content name="h3">A</content> 
     <content name="h3">B</content> 
     <content name="h3">C</content> 
     <content name="h3">D</content> 
     <content name="h3">E</content> 
     <content name="h3">F</content> 
     <content name="h3">G</content> 
    </content> 
</document> 
</vce> 

In der Beschreibung kann ich akzeptieren nur A, B und C, sondern müssen auch sicher, dass es keine Duplikate machen. Daher sollte meine gewünschte Ausgabe sein:

<vce> 
<document> 
    <content name="title">X</content> 
    <content name="description"> 
     <content name="h3">A</content> 
     <content name="h3">B</content> 
     <content name="h3">C</content> 
    </content> 
</document> 
</vce> 

Dies ist, was ich gerade arbeite mit:

<xsl:template match="/"> 
    <vce> 
    <document> 
     <content name="title"> 
     <xsl:for-each select="//document/content[@name='title']"> 
      <xsl:value-of select="." /> 
     </xsl:for-each> 
     </content> 

     <content name="description"> 
     <xsl:for-each select="//document/content[@name='h3']"> 
      <xsl:if test="not(preceding::document[content[@name='h3']/text() = current()/content[@name='h3']/text()])"> 
      <content name="h3"> 
       <xsl:value-of select="." /> 
      </content> 
      </xsl:if> 
     </xsl:for-each> 
     </content> 
    </document> 
    </vce> 
</xsl:template> 

Dank im Voraus für Ihre Bemühungen Jungs!

+0

* I ein xsl Anfänger bin und ich habe versucht, das jetzt für ein paar Tage arbeiten zu erhalten * ... und wo ist diese XSLT-Studie? – Parfait

+0

Welche Version von XSLT? –

+0

Ich arbeite mit Version 1.0 –

Antwort

0

Da sich ein Großteil Ihrer Eingabe nicht in der Ausgabe ändert, würde ich mit einer identity transform starten, um alles standardmäßig zu kopieren. Dann können Sie Vorlagen hinzufügen, um die Identitätstransformation bei Bedarf zu überschreiben.

Sie möchten auch die Muenchian Method Gruppierung verwenden, um die Duplikate zu entfernen.

Ihre Eingabe ist super einfach, also hoffentlich wird dies mit Ihren tatsächlichen Daten arbeiten.

XML-Eingabe

<vce> 
    <document> 
     <content name="title">X</content> 
     <content name="description"> 
      <content name="h3">A</content> 
      <content name="h3">B</content> 
      <content name="h3">C</content> 
      <content name="h3">A</content> 
      <content name="h3">B</content> 
      <content name="h3">C</content> 
      <content name="h3">D</content> 
      <content name="h3">E</content> 
      <content name="h3">F</content> 
      <content name="h3">G</content> 
     </content> 
    </document> 
</vce> 

XSLT 1,0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="desc" match="content[@name='description']/content" use="."/> 

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

    <xsl:template match="content[@name='description']"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:for-each select="content[.='A' or .='B' or .='C'] 
     [count(.|key('desc',.)[1])=1]"> 
     <xsl:apply-templates select="."/> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Ausgabe

<vce> 
    <document> 
     <content name="title">X</content> 
     <content name="description"> 
     <content name="h3">A</content> 
     <content name="h3">B</content> 
     <content name="h3">C</content> 
     </content> 
    </document> 
</vce> 

Hier ist eine andere Version th at macht es einfacher, die "erlaubten" Elemente zu verwalten.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="allowed" select="'|Step A.|Step B.|Step C.|'"/> 

    <xsl:key name="desc" match="content[@name='description']/content" use="."/> 

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

    <xsl:template match="content[@name='description']"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:for-each select="content[contains($allowed,concat('|',normalize-space(),'|'))] 
     [count(.|key('desc',.)[1])=1]"> 
     <xsl:apply-templates select="."/> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Wie wäre es, wenn der Inhalt, den ich suchte, komplizierter war als nur A, B und C. Zum Beispiel, wenn ich nach einem Text suche, der das Schlüsselwort 'step' oder a enthält Nummer gefolgt von '.' (dh '1.'), wird

+0

@MarkB - Ja, das sollte noch funktionieren In Ordnung, Sie sollten "normalize-space()' anstatt nur '.' verwenden, aber nur so, dass irgendwelche irrelevanten Leerzeichen nicht in den Vergleich einbezogen werden. Beispiel:' normalize-space() = 'Schritt 1.'' I Außerdem wurde ein weiteres Beispiel hinzugefügt, das einen xsl: param verwendet, um den Inhalt zu vergleichen. Das könnte die Verwaltung erleichtern. Es sollte zumindest ein guter Anfang sein. –

Verwandte Themen