1

私たちのサービスの 1 つは、todo のコレクションをリストする xml ドキュメントを提供します。Todo は、todolist の下にネストできるように構造化されています。すべてのシングルtodo itemには親がありtodo listます。XSL を使用して、現在の親の todo アイテムの数を表示する必要がありますtodo-list。以下のxmlの構造を見つけてください

<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>

の最初の反復では、合計でTodoList ID = 1カウントを取得できるはずです。最初の todo アイテム コレクションに3 + 4 = 73 つあり、次に子 todo アイテム コレクションに4 つあるため ( ParentId = 1)。ここでのネスティングは 1 レベルですが、N レベルになるように設計されています。

注: ここでクエリをオンラインで試すことができますhttp://chris.photobooks.com/xml/default.htm

4

1 に答える 1

2

この変換

<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>

次のXMLドキュメントに適用した場合(提供されているものに基づいていますが、階層が深くなっています):

<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>

必要な正しい結果を生成します

<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>

説明

これは2パス変換です。

  1. 最初のパスで、ドキュメントは親->id関係に基づいてフラットから階層に変換されます。

  2. 2番目のパスでは、pass1の結果がフラットドキュメントに変換されます。要素は、最も内側に含まれるサブツリー内Countのすべての要素の合計を含むように調整されます。Count

  3. TodoList最終結果に、でソートされた要素を含める場合は、3番目のパスが必要になることがありますId

于 2012-04-13T12:59:03.323 に答える