2012-04-04 5 views
3

Ich versuche, eine Liste der Attributwerte der untergeordneten Elemente eines Elements abzurufen, aber ich möchte, dass die Werte nur einmal angezeigt werden.Wählen Sie in XSLT im Verhältnis zu jedem Element darktinct

Zum Beispiel habe ich die folgende XML

<root> 
    <sec> 
     <nom-title> 
      <nom-chapter> 
       <nom-article><data att="1.1"/></nom-article> 
       <nom-article> 
        <nom-item><data att="1.1"/></nom-item> 
        <nom-item><data att="1.2"/></nom-item> 
       </nom-article> 
      </nom-chapter> 
      <nom-chapter> 
       <nom-article><data att="2.1"/></nom-article> 
       <nom-article><data att="1.1"/></nom-article> 
      </nom-chapter> 
     </nom-title> 
     <nom-title> 
      <nom-chapter> 
       <nom-article><data att="1.1"/></nom-article> 
      </nom-chapter> 
     </nom-title> 
    </sec> 
</root> 

Und ich möchte ein Ergebnis wie folgt aus:

<root> 
    <nom-title> 
     <att>1.1</att> 
     <att>1.2</att> 
     <att>2.1</att> 
     <nom-chapter> 
      <att>1.1</att> 
      <att>1.2</att> 
      <nom-article> 
       <att>1.1</att> 
      </nom-article> 
      <nom-article> 
       <att>1.1</att> 
       <att>1.2</att> 
       <nom-item><att>1.1</att></nom-item> 
       <nom-item><att>1.2</att></nom-item> 
      </nom-article> 
     </nom-chapter> 
    </nom-title> 
    <nom-title> 
     <att>1.1</att> 
     <nom-chapter> 
      <att>1.1</att> 
      <nom-article> 
       <att>1.1</att> 
      </nom-article> 
     </nom-chapter> 
    </nom-title> 
</root> 

Ich habe versucht, die xsl zu verwenden: Schlüsselelement, aber es gibt nur die Wert für ein Element. Im Beispiel gibt es nur 1,1 für den ersten Titel, aber nicht für den zweiten zurück. Das xsl ich verwendet habe:

<xsl:key name="allAtt" 
    match="//*[starts-with(name(.),'nom-')]/data" 
    use="@att"/> 
<xsl:template match="nom-title|nom-chapter|nom-article|nom-item"> 
    <xsl:element name="name(.)"> 
     <xsl:apply-templates select=".//*[starts-with(name(.),'nom-')]/data 
    </xsl:element> 
</xsl:template>   
<xsl:template match="data"> 
     <xsl:variable name="att" select="@att"/> 
     <xsl:if test="generate-id(.)=generate-id(key('allAtt',$att)[1]"> 
      <xsl:element name="att"><xsl:value-of select="$att"></xsl:element> 
     </xsl:if> 
</xsl:template> 
+2

Nach meiner Erfahrung mit xslt benötigt man zunächst ein gültiges xml. Es sieht so aus, als wäre das Element "nom-article" nicht geschlossen. Ich möchte versuchen, das zuerst zu beheben. –

+1

Ich stimme mit Justin überein, bitte zeigen Sie uns zuerst ein wohlgeformtes XML-Eingabesample, momentan ist die Struktur der Eingabe nicht klar, wobei mehrere Tags nicht richtig geschlossen werden (zB '', ') '). –

+0

Entschuldigung, falsche Kopie-Paste, ich habe es behoben. – claudex

Antwort

2

Diese Transformation:

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

<xsl:key name="kData-nom-article" match="data" use= 
"concat(generate-id(ancestor::nom-article[1]), 
     '+', @att)"/> 
<xsl:key name="kData-nom-chapter" match="data" use= 
"concat(generate-id(ancestor::nom-chapter[1]), 
     '+', @att)"/> 
<xsl:key name="kData-nom-title" match="data" use= 
"concat(generate-id(ancestor::nom-title[1]), 
     '+', @att)"/> 

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

<xsl:template match="sec"><xsl:apply-templates/></xsl:template> 

<xsl:template match="nom-title|nom-article|nom-chapter"> 
    <xsl:copy> 
    <xsl:apply-templates mode="list" select= 
    ".//data[generate-id() 
      = 
       generate-id(key(concat('kData-', name(current())), 
           concat(generate-id(current()), 
            '+', @att 
            ) 
          ) 
           [1] 
         ) 
      ]"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="data" mode="list"> 
    <att><xsl:value-of select="@att"/></att> 
</xsl:template> 

<xsl:template match="non-item/data"> 
    <att><xsl:value-of select="@att"/></att> 
</xsl:template> 

<xsl:template match="*[not(self::nom-item)]/data"/> 
</xsl:stylesheet> 

wenn auf dem mitgelieferten XML-Dokument angelegt:

<root> 
    <sec> 
     <nom-title> 
      <nom-chapter> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
       <nom-article> 
        <nom-item> 
         <data att="1.1"/> 
        </nom-item> 
        <nom-item> 
         <data att="1.2"/> 
        </nom-item> 
       </nom-article> 
      </nom-chapter> 
      <nom-chapter> 
       <nom-article> 
        <data att="2.1"/> 
       </nom-article> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
      </nom-chapter> 
     </nom-title> 
     <nom-title> 
      <nom-chapter> 
       <nom-article> 
        <data att="1.1"/> 
       </nom-article> 
      </nom-chapter> 
     </nom-title> 
    </sec> 
</root> 

erzeugt das gewünschte, korrekte Ergebnis :

<root> 
    <nom-title> 
     <att>1.1</att> 
     <att>1.2</att> 
     <att>2.1</att> 
     <nom-chapter> 
     <att>1.1</att> 
     <att>1.2</att> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     <nom-article> 
      <att>1.1</att> 
      <att>1.2</att> 
      <nom-item> 
       <data att="1.1"/> 
      </nom-item> 
      <nom-item> 
       <data att="1.2"/> 
      </nom-item> 
     </nom-article> 
     </nom-chapter> 
     <nom-chapter> 
     <att>2.1</att> 
     <att>1.1</att> 
     <nom-article> 
      <att>2.1</att> 
     </nom-article> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     </nom-chapter> 
    </nom-title> 
    <nom-title> 
     <att>1.1</att> 
     <nom-chapter> 
     <att>1.1</att> 
     <nom-article> 
      <att>1.1</att> 
     </nom-article> 
     </nom-chapter> 
    </nom-title> 
</root> 

Erklärung: drei verschiedene Muench-Gruppierungen als einen Ausdruck, durch dynamisch den Namen des Schlüssels für die tatsächliche Gruppierung der Konstruktion durchgeführt werden.

Denken Sie daran,: Der Schlüsselname ist eine Zeichenfolge und bei Bedarf (wie in diesem Fall), kann der Name dynamisch konstruiert werden, oder als Parameter übergeben.

Verwandte Themen