3

私はこれについて頭を悩ませようとしていますが、それを説明する最も簡単な方法は、以下に示すことだと思います. 私はこれを見てきましが、最後にも一致するスタンドアロンのアイテムがあるため、常に当てはまるとは限りません。

一見トリッキーな部分は、Whatever3からWhatever6、次にWhatever7とWhatever8、そして最後にWhatever9の新しい位置です.それらはグループ化され、元のシーケンスが維持される必要があります. (私の命名は無視してください。xsl:sort を使用する方法はありません)

xsl:for-each と xsl:if を内部で検討しましたが、問題は、「グループ」と「非グループ」のアイテムの数を保証できないことです。

ありがとう!

XML

<root>
   <item>
      <position>1</position>
      <label>Whatever1</label>
   </item>
   <item>
      <position>2</position>
      <label>Whatever2</label>
   </item>
   <item>
      <position>3</position>
      <label>Whatever3</label>
      <marker id="unique1">start_group</marker>
   </item>
   <item>
      <position>4</position>
      <label>Whatever4</label>
   </item>
   <item>
      <position>5</position>
      <label>Whatever5</label>
   </item>
   <item>
      <position>6</position>
      <label>Whatever6</label>
      <marker>last_in_group</marker>
   </item>
   <item>
      <position>7</position>
      <label>Whatever7</label>
      <marker id="unique2">start_group</marker>
   </item>
   <item>
      <position>8</position>
      <label>Whatever8</label>
      <marker>last_in_group</marker>
   </item>  
   <item>
      <position>9</position>
      <label>Whatever9</label>
   </item>
</root>

結果

<structure>
   <item>
      <position>1</position>
      <label>Whatever1</label>
    </item>
   <item>
      <position>2</position>
      <label>Whatever2</label>
    </item>
    <group position="3" id="unique1">
        <item>
          <position>1</position>
          <label>Whatever3</label>
        </item>
        <item>
          <position>2</position>
          <label>Whatever4</label>
        </item>
        <item>
          <position>3</position>
          <label>Whatever5</label>
        </item>
        <item>
          <position>4</position>
          <label>Whatever6</label>
        </item>
    </group>
    <group position="4" id="uniqueid2">
        <item>
          <position>1</position>
          <label>Whatever7</label>
        </item>
        <item>
          <position>2</position>
          <label>Whatever8</label>
        </item>
    </group>
    <item>
      <position>**5**</position>
      <label>Whatever9</label>
    </item>
</structure>

======================

これが私がこれまでに持っているものです.私が持っている唯一の問題は(それが面倒なこと以外に)Whatever4とWhatever5がグループの外に現れていることです.

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

  <xsl:template match="root">
  <structure>
    <xsl:apply-templates select="item[not(marker)] | item[marker='start_group']"/>
  </structure>
 </xsl:template>

  <xsl:template match="item[marker='start_group']">
   <group>
    <xsl:variable name="currentPosition" select="number(position/text())"/>
    <xsl:variable name="lastGroup" select="count(following-sibling::*[local-name() = 'item' and marker='last_in_group'][1]/preceding-sibling::*) + 1"/>

    <xsl:attribute name="position">
        <xsl:value-of select="$currentPosition"/>
    </xsl:attribute>
    <xsl:attribute name="id">
        <xsl:value-of select="marker/@id"/>
    </xsl:attribute>

   <item>
    <position><xsl:value-of select="number(position/text()) - $currentPosition + 1"/></position>
    <label><xsl:value-of select="label/text()"/></label>
   </item>

   <!-- position() gets reset in for-loop, so need to adjust with outer position -->
   <xsl:for-each select="following-sibling::item[(position() + $currentPosition) &lt;= $lastGroup]">
         <item>
                <position><xsl:value-of select="number(position/text()) - $currentPosition + 1"/></position>
                <label><xsl:value-of select="label/text()"/></label>
         </item>
    </xsl:for-each>
   </group>
 </xsl:template>

  <xsl:template match="item[not(marker)]">
   <item>
    <position><xsl:value-of select="position/text()"/></position>
    <label><xsl:value-of select="label/text()"/></label>
   </item>
 </xsl:template>

</xsl:stylesheet>
4

1 に答える 1

3

I. XSLT 1.0 ソリューション:

この変換:

<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="kFollowing"
  match="item[not(marker[. = 'start_group'])
            and
              preceding-sibling::*[marker][1]/marker = 'start_group'
             ]"
  use="generate-id(preceding-sibling::*
                    [marker[. = 'start_group']]
                     [1])"/>

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

 <xsl:template match="item[marker[. = 'start_group']]">
   <group position="{1 +count(preceding-sibling::*[. = 'start_group'])}"
   id="{marker/@id}">
     <xsl:copy-of select=".|key('kFollowing', generate-id())"/>
   </group>
 </xsl:template>

 <xsl:template match=
  "item[not(marker[. = 'start_group'])
      and
       preceding-sibling::*[marker][1]/marker = 'start_group'
       ]"/>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<root>
    <item>
        <position>1</position>
        <label>Whatever1</label>
    </item>
    <item>
        <position>2</position>
        <label>Whatever2</label>
    </item>
    <item>
        <position>3</position>
        <label>Whatever3</label>
        <marker id="unique1">start_group</marker>
    </item>
    <item>
        <position>4</position>
        <label>Whatever4</label>
    </item>
    <item>
        <position>5</position>
        <label>Whatever5</label>
    </item>
    <item>
        <position>6</position>
        <label>Whatever6</label>
        <marker>last_in_group</marker>
    </item>
    <item>
        <position>7</position>
        <label>Whatever7</label>
        <marker id="unique2">start_group</marker>
    </item>
    <item>
        <position>8</position>
        <label>Whatever8</label>
        <marker>last_in_group</marker>
    </item>
    <item>
        <position>9</position>
        <label>Whatever9</label>
    </item>
</root>

必要な正しい結果が生成されます。

<root>
   <item>
      <position>1</position>
      <label>Whatever1</label>
   </item>
   <item>
      <position>2</position>
      <label>Whatever2</label>
   </item>
   <group position="1" id="unique1">
      <item>
         <position>3</position>
         <label>Whatever3</label>
         <marker id="unique1">start_group</marker>
      </item>
      <item>
         <position>4</position>
         <label>Whatever4</label>
      </item>
      <item>
         <position>5</position>
         <label>Whatever5</label>
      </item>
      <item>
         <position>6</position>
         <label>Whatever6</label>
         <marker>last_in_group</marker>
      </item>
   </group>
   <group position="1" id="unique2">
      <item>
         <position>7</position>
         <label>Whatever7</label>
         <marker id="unique2">start_group</marker>
      </item>
      <item>
         <position>8</position>
         <label>Whatever8</label>
         <marker>last_in_group</marker>
      </item>
   </group>
   <item>
      <position>9</position>
      <label>Whatever9</label>
   </item>
</root>

Ⅱ.XSLT 2.0 ソリューション:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/*">
  <root>
   <xsl:for-each-group select="item" group-starting-with=
   "*[marker eq 'start_group'
    or
      not(marker)
    and
      preceding-sibling::*[marker][1]/marker eq 'last_in_group'
     ]
   ">
     <xsl:choose>
       <xsl:when test="current-group()[1]/marker">
               <group position=
               "{1 +count(current-group()[1]
                            /preceding-sibling::*
                                  [marker = 'start_group'])}"
               id="{marker/@id}">
                 <xsl:apply-templates select="current-group()"/>
               </group>
       </xsl:when>
       <xsl:otherwise>
        <xsl:apply-templates select="current-group()"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:for-each-group>
  </root>
 </xsl:template>
</xsl:stylesheet>

この XSLT 2.0 変換を同じ XML ドキュメント (上記) に適用すると、同じ正しい結果が生成されます。

于 2012-06-22T03:57:34.327 に答える