2012-04-13 11 views
1

Einer unserer Service bietet ein XML-Dokument, das Auflistung von Todo's auflisten. Todo's wurden so strukturiert, dass sie unter einem Todolisten nestbar sind. Jede einzelne todo item wird über die todo list verfügen. Ich muss XSL verwenden, um eine Anzahl von Todo-Items für das aktuelle Eltern todo-list anzuzeigen. Bitte entnehmen Sie die Struktur des XML unterWie zähle ich rekursiv die Anzahl der Todos in XSLT 1.0

<TodoListCollection> 
    <TodoList> 
    <Id>1</Id> 
    <ParentId></ParentId> 
    <Count>3</Count> 
    <TodoItemCollection> 
     <TodoItem></TodoItem> 
     <TodoItem></TodoItem> 
     <TodoItem></TodoItem> 
    </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
    <Id>2</Id> 
    <ParentId>1</ParentId> 
    <Count>4</Count> 
    <TodoItemCollection> 
     <TodoItem></TodoItem> 
     <TodoItem></TodoItem> 
     <TodoItem></TodoItem> 
     <TodoItem></TodoItem> 
    </TodoItemCollection> 
    </TodoList> 
</TodoListCollection> 

In erster Iteration für TodoList ID = 1, soll ich in der Lage sein, wie 3 + 4 = 7 insgesamt zählen zu lassen. Da gibt es in der ersten todo Artikelsammlung und dann in der Kind Todo Artikelsammlung (ParentId = 1). Die Verschachtelung hier ist nur eine Ebene, aber wir haben sie auf N-Ebene entworfen.

Hinweis: Sie können Ihre Anfragen Online hier http://chris.photobooks.com/xml/default.htm

Antwort

2

Diese Transformation versuchen:

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

<xsl:key name="kChildren" match="TodoList" use="ParentId"/> 

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

<xsl:template match="/*"> 
    <xsl:variable name="vrtfPass1"> 
    <xsl:copy> 
    <xsl:apply-templates select="key('kChildren', '')"/> 
    </xsl:copy> 
    </xsl:variable> 

    <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)"/> 
    <xsl:apply-templates select="$vPass1/*" mode="pass2"/> 
</xsl:template> 

<xsl:template match="TodoList"> 
    <xsl:copy> 
    <xsl:apply-templates /> 
    <xsl:apply-templates select="key('kChildren', Id)"/> 
    </xsl:copy> 
</xsl:template> 

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

<xsl:template match="TodoList" mode="pass2"> 
    <xsl:copy> 
    <xsl:apply-templates select="*[not(self::TodoList)]" mode="pass2"/> 
    </xsl:copy> 
    <xsl:apply-templates select="TodoList" mode="pass2"/> 
</xsl:template> 

<xsl:template match="Count" mode="pass2"> 
    <Count> 
    <xsl:value-of select="sum(..//Count)"/> 
    </Count> 
</xsl:template> 
</xsl:stylesheet> 

bei der Anwendung auf dem folgenden XML-Dokument (basierend auf dem vorgesehen ist, aber mit tieferer Hierarchie):

<TodoListCollection> 
    <TodoList> 
     <Id>1</Id> 
     <ParentId></ParentId> 
     <Count>3</Count> 
     <TodoItemCollection> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>2</Id> 
     <ParentId>1</ParentId> 
     <Count>7</Count> 
     <TodoItemCollection> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>3</Id> 
     <ParentId>2</ParentId> 
     <Count>5</Count> 
     <TodoItemCollection> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>4</Id> 
     <ParentId>3</ParentId> 
     <Count>3</Count> 
     <TodoItemCollection> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>5</Id> 
     <ParentId>2</ParentId> 
     <Count>1</Count> 
     <TodoItemCollection> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
      <TodoItem></TodoItem> 
     </TodoItemCollection> 
    </TodoList> 
</TodoListCollection> 

erzeugt das gewünschte, korrekte Ergebnis:

<TodoListCollection> 
    <TodoList> 
     <Id>1</Id> 
     <ParentId/> 
     <Count>19</Count> 
     <TodoItemCollection> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>2</Id> 
     <ParentId>1</ParentId> 
     <Count>16</Count> 
     <TodoItemCollection> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>3</Id> 
     <ParentId>2</ParentId> 
     <Count>8</Count> 
     <TodoItemCollection> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>4</Id> 
     <ParentId>3</ParentId> 
     <Count>3</Count> 
     <TodoItemCollection> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     </TodoItemCollection> 
    </TodoList> 
    <TodoList> 
     <Id>5</Id> 
     <ParentId>2</ParentId> 
     <Count>1</Count> 
     <TodoItemCollection> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     <TodoItem/> 
     </TodoItemCollection> 
    </TodoList> 
</TodoListCollection> 

Erklärung:

Dies ist eine Zwei-Pass-Transformation:

  1. In dem ersten das Dokument übergeben wird umgewandelt von flach zu hierarchisch basierend auf der Eltern -> ID-Beziehung.

  2. Im zweiten Durchgang wird das Ergebnis von pass1 zurück in ein flaches Dokument konvertiert. Count Elemente werden angepasst, um die Summe aller Count Elemente in ihrem innersten enthaltenden Teilbaum zu enthalten.

  3. Ein dritter Durchgang ist möglicherweise erforderlich, wenn das Endergebnis die TodoList Elemente enthalten soll, sortiert nach Id.

+0

+1 Brillante Antwort. –

+0

@NickRyan: Gern geschehen. –

+0

+1 Hat, was es sagt, aber Rekursion könnte in XSLT freundlicher gewesen sein. Syntax und Idee ist fantastisch – Deeptechtons

Verwandte Themen