1

一連の同じレベルのノードである入力ドキュメントが与えられた場合、2 つのフラグ (それ自体がノード) の間にあるノードを見つけたいと考えています。フラグは複数回使用でき、最終的な結果には、同じフラグ間のすべてのコンテンツがグループ化されている必要があります。私はこれに打ちのめしています。

次の入力ドキュメントがあるとします。

<root>
    <p class="text">Hello world 1.</p>
    <p class="text">Hello world 2.</p>
    <p class="text">Hello world 3.</p>
    <p class="excerptstartone">Dummy text</p> <!-- this flag identifies the start of the nodes I want to select -->
    <p class="text">Hello world 4.</p>
    <p class="text">Hello world 5.</p>
    <p class="text">Hello world 6.</p>
    <p class="excerptendone">Dummy text</p> <!-- this flag identifies the end of the nodes I want to select -->
    <p class="text">Hello world 7.</p>
    <p class="excerptstarttwo">Dummy text</p> <!-- this flag identifies the start of the nodes I want to select -->
    <p class="text">Hello world 8.</p>
    <p class="excerptendtwo">Dummy text</p> <!-- this flag identifies the end of the nodes I want to select -->
    <p class="text">Hello world 9.</p>
    <p class="excerptstartone">Dummy text for starting a new excerpt</p> <!-- this flag identifies the start of the nodes I want to select -->
    <p class="text">Hello world 10.</p>
    <p class="text">Hello world 11.</p>
    <p class="excerptendone">Dummy text</p> <!-- this flag identifies the end of the nodes I want to select -->
    <p class="text">Hello world 12.</p>
    <p class="text">Hello world 13.</p>
    <p class="text">Hello world 14.</p>
    <p class="text">Hello world 15.</p>
    <p class="text">Hello world 16.</p>
    <p class="text">Hello world 17.</p>
</root>

私はこの出力が欲しい:

<root>
    <p class="excerptstartone">Dummy text</p>
    <p class="text">Hello world 4.</p>
    <p class="text">Hello world 5.</p>
    <p class="text">Hello world 6.</p>
    <p class="text">Hello world 10.</p>
    <p class="text">Hello world 11.</p>
    <p class="excerptendone">Dummy text</p>
    <p class="excerptstarttwo">Dummy text</p>
    <p class="text">Hello world 8.</p>
    <p class="excerptendtwo">Dummy text</p>
</root>

注: フラグは常に "excerptstart" と "excerptend" で始まり、フラグのサフィックスは常に一致します (つまり、ビジネス ルールにより、"excerptstartone" がある場合は常に "excerptendone" が存在することが保証されます)。

これは私がこれまでに持っているものです。excerptstart サフィックス (つまり、「1」、「2」) をハードコーディングしている限り、必要なコレクションを見つけることができます。接尾辞をハードコードする必要がないように、一般化しようとすることに固執しています(結果ツリーに開始/終了段落の「フラグ」を保持することは気にしないと言うべきです;私はそれらをハードコードしましたここでは、結果ツリーを評価する際の便宜のために):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="root">
    <root>
        <p class="excerptstartone">Dummy text</p>
        <xsl:for-each select="p[@class='excerptstartone']">
           <xsl:sequence select="following-sibling::node() intersect following-sibling::p[@class='excerptendone'][1]/preceding-sibling::node()"/>   
       </xsl:for-each>
        <p class="excerptendone">Dummy text</p>
        <p class="excerptstarttwo">Dummy text</p>
        <xsl:for-each select="p[@class='excerptstarttwo']">
            <xsl:sequence select="following-sibling::node() intersect following-sibling::p[@class='excerptendtwo'][1]/preceding-sibling::node()"/>   
        </xsl:for-each>
        <p class="excerptendtwo">Dummy text</p>
    </root>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
4

3 に答える 3

2

たとえば、この Kayessian methodを見てください。

またはこれを試してください:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kFollowing" match="p"
          use="generate-id(preceding-sibling::p[starts-with(@class, 'excerptstart')][1])"/>

<xsl:key name="kExcerptstart" match="p[starts-with(@class, 'excerptstart')]"  use="@class"/>

    <xsl:template match="/*">
        <xsl:copy>  
            <xsl:apply-templates select="p"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="p" />
 <xsl:template match="p[ generate-id() = generate-id( key( 'kExcerptstart', @class)[1])] ">
     <xsl:copy-of select="."/>
     <xsl:variable name="start" select="@class" />
     <xsl:for-each select=" key( 'kExcerptstart', $start) " >
      <xsl:variable name="end" select="following-sibling::p[starts-with(@class, 'excerptend')][1]"/>
      <xsl:variable name="ns1" select="following-sibling::*" />
      <xsl:variable name="ns2" select="$end/preceding-sibling::*" />
      <!--<xsl:value-of select="count($ns1)"/>,<xsl:value-of select="count($ns2)"/>-->
      <xsl:copy-of select="$ns1[count(.|$ns2) = count($ns2)]"/>
     </xsl:for-each>
     <xsl:copy-of select="following-sibling::p[starts-with(@class, 'excerptend')][1]"/>
 </xsl:template>
</xsl:stylesheet>

次の出力が生成されます。

<root>
  <p class="excerptstartone">Dummy text</p>
  <p class="text">Hello world 4.</p>
  <p class="text">Hello world 5.</p>
  <p class="text">Hello world 6.</p>
  <p class="text">Hello world 10.</p>
  <p class="text">Hello world 11.</p>
  <p class="excerptendone">Dummy text</p>
  <p class="excerptstarttwo">Dummy text</p>
  <p class="text">Hello world 8.</p>
  <p class="excerptendtwo">Dummy text</p>
</root>
于 2013-06-15T15:03:07.143 に答える
1

(また、結果ツリーに段落の開始/終了の「フラグ」を保持することは気にしないとも言わなければなりません。ここでは、結果ツリーを評価する際の便宜上、これらをハードコーディングしました)

grouping だけを使用した簡単なソリューションを次に示します

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

 <xsl:template match="/*">
  <root>
     <xsl:for-each-group select=
     "p[@class eq 'text']
         [preceding-sibling::p[starts-with(@class, 'excerpt')][1]
             [starts-with(@class, 'excerptstart')]
         ]"
          group-by="preceding-sibling::p[starts-with(@class, 'excerpt')][1]/@class">

        <xsl:sequence select="current-group()"/>
     </xsl:for-each-group>
  </root>
 </xsl:template>
</xsl:stylesheet>

この変換が提供された XML ドキュメントに適用されると、次のようになります。

<root>
    <p class="text">Hello world 1.</p>
    <p class="text">Hello world 2.</p>
    <p class="text">Hello world 3.</p>
    <p class="excerptstartone">Dummy text</p> <!-- this flag identifies the start of the nodes I want to select -->
    <p class="text">Hello world 4.</p>
    <p class="text">Hello world 5.</p>
    <p class="text">Hello world 6.</p>
    <p class="excerptendone">Dummy text</p> <!-- this flag identifies the end of the nodes I want to select -->
    <p class="text">Hello world 7.</p>
    <p class="excerptstarttwo">Dummy text</p> <!-- this flag identifies the start of the nodes I want to select -->
    <p class="text">Hello world 8.</p>
    <p class="excerptendtwo">Dummy text</p> <!-- this flag identifies the end of the nodes I want to select -->
    <p class="text">Hello world 9.</p>
    <p class="excerptstartone">Dummy text for starting a new excerpt</p> <!-- this flag identifies the start of the nodes I want to select -->
    <p class="text">Hello world 10.</p>
    <p class="text">Hello world 11.</p>
    <p class="excerptendone">Dummy text</p> <!-- this flag identifies the end of the nodes I want to select -->
    <p class="text">Hello world 12.</p>
    <p class="text">Hello world 13.</p>
    <p class="text">Hello world 14.</p>
    <p class="text">Hello world 15.</p>
    <p class="text">Hello world 16.</p>
    <p class="text">Hello world 17.</p>
</root>

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

<root>
   <p class="text">Hello world 4.</p>
   <p class="text">Hello world 5.</p>
   <p class="text">Hello world 6.</p>
   <p class="text">Hello world 10.</p>
   <p class="text">Hello world 11.</p>
   <p class="text">Hello world 8.</p>
</root>
于 2013-06-15T19:17:31.417 に答える
0

これは、(2つのfor-eachを使用するため)少し不格好ですが、私がやりたいことに対する一般的な解決策を提供します:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="root">
    <root>
        <xsl:variable name="uniqueExcerptClasses" select="distinct-values(//@class[starts-with(.,'excerptstart')])"/>
        <xsl:variable name="context" select="."/>
        <xsl:for-each select="$uniqueExcerptClasses">
            <xsl:text>
        </xsl:text><p>start excert</p><xsl:text>
        </xsl:text>
            <xsl:variable name="curExcerpt" select="."/>
            <xsl:for-each select="$context/p[@class=$curExcerpt]">
               <xsl:sequence select="following-sibling::node() intersect following-sibling::p[@class=replace($curExcerpt,'start','end')][1]/preceding-sibling::node()"/>   
           </xsl:for-each>
            <xsl:text>
        </xsl:text><p>end excert</p><xsl:text>
        </xsl:text>
        </xsl:for-each>
    </root>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
于 2013-06-15T17:29:33.380 に答える