-4

基于下面的源 XML,我想捕获<emphasis>不包含<emphasis bold="yes">NOTE#:的文本节点和元素</emphasis>,以及它们对应的<emphasis bold="yes">NOTE#:</emphasis>元素。

源 XML:

<section>
  <para>
    <emphasis bold="yes">NOTE1:</emphasis> This is the text of the first note 1 <emphasis bold="yes">that should only be in the <emphasis italic="yes">first</emphasis> subsection occurance of note one.</emphasis>. This is the second sentence of the first note one. <emphasis italic="yes">Here is some other text</emphasis> that can appear. <emphasis bold="yes">Marvin Gaye is an excellent musician1.</emphasis> Play it for your girlfriend1 <emphasis italic="yes">now1.</emphasis>.
    <emphasis bold="yes">NOTE2:</emphasis> This is the text of  the first note two2.1 <emphasis italic="yes">The Isley Brothers are also good.2.1</emphasis>
    <emphasis bold="yes">NOTE1:</emphasis> This is the text of the second note one.1.2 <emphasis italic="yes">My girlfriend loves them1.2</emphasis>
    <emphasis bold="yes">NOTE3:</emphasis> This is the text of the first note three3.1.
    <emphasis bold="yes">NOTE1:</emphasis> This is the text of the third note one.1.3<emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
    <emphasis bold="yes">NOTE3:</emphasis> This is the text of the second note three.3.2<emphasis italic="yes">Steak and potatos3.2</emphasis>
    <emphasis bold="yes">NOTE2:</emphasis> This is the text of the second note two.2.2<emphasis italic="yes">And then some wine2.2</emphasis>
  </para>
</section>

当前 XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

  <xsl:template match="section">
    <root>
      <xsl:apply-templates select="*|@*|text()"/>
    </root>
  </xsl:template>

  <xsl:template match="para/emphasis[preceding-sibling::emphasis[@bold='yes' and text()='NOTE1:']]"/>
  <xsl:template match="para/emphasis[preceding-sibling::emphasis[@bold='yes' and text()='NOTE2:']]"/>
  <xsl:template match="para/emphasis[preceding-sibling::emphasis[@bold='yes' and text()='NOTE3:']]"/>
  <xsl:template match="para/text()[preceding-sibling::emphasis[@bold='yes' and text()='NOTE1:']]"/>
  <xsl:template match="para/text()[preceding-sibling::emphasis[@bold='yes' and text()='NOTE2:']]"/>
  <xsl:template match="para/text()[preceding-sibling::emphasis[@bold='yes' and text()='NOTE3:']]"/>

  <xsl:template match="para/emphasis[@bold='yes' and text()='NOTE1:' and not(position()=last())]">
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis>
        <xsl:copy-of
          select="following-sibling::text()[not(preceding-sibling::emphasis[@bold='yes' and text()='NOTE2:'])  and not(preceding-sibling::emphasis[@bold='yes' and text()='NOTE3:'])] |following-sibling::emphasis[not(contains(string(), 'NOTE1:'))  and  not(contains(string(), 'NOTE2:'))  and not(contains(string(), 'NOTE3:'))]"
        />
      </para>
    </subsection>
  </xsl:template>

  <xsl:template match="para/emphasis[position()=last() and position() > 1  and @bold='yes' and text()='NOTE1:']">
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis>
        <xsl:copy-of
          select="following-sibling::text()[position() = 1]|following-sibling::emphasis[not(contains(string(), 'NOTE1:'))  and  not(contains(string(), 'NOTE2:'))  and not(contains(string(), 'NOTE3:'))]"
        />
      </para>
    </subsection>
  </xsl:template>

  <xsl:template match="para/emphasis[@bold='yes' and text()='NOTE2:' and not(position()=last())]">
    <subsection>
      <para>
        <emphasis bold="yes">NOTE2:</emphasis>
        <xsl:copy-of
          select="following-sibling::text()[not(preceding-sibling::emphasis[@bold='yes' and text()='NOTE1:'])  and not(preceding-sibling::emphasis[@bold='yes' and text()='NOTE3:'])] |following-sibling::emphasis[not(contains(string(), 'NOTE1:'))  and  not(contains(string(), 'NOTE2:'))  and not(contains(string(), 'NOTE3:'))]"
        />
      </para>
    </subsection>
  </xsl:template>

  <xsl:template match="para/emphasis[position()=last() and position() > 1 and @bold='yes' and text()='NOTE2:']">
    <note>
      <para>
        <emphasis bold="yes">NOTE2:</emphasis>
        <xsl:copy-of
          select="following-sibling::text()[position() = 1]|following-sibling::emphasis[not(contains(string(), 'NOTE1:'))  and  not(contains(string(), 'NOTE2:')) and not(contains(string(), 'NOTE3:'))  ]"
        />
      </para>
    </note>
  </xsl:template>

  <xsl:template match="para/emphasis[@bold='yes' and text()='NOTE3:' and not(position()=last())]">
    <note>
      <para>
        <emphasis bold="yes">NOTE3:</emphasis>
        <xsl:copy-of
          select="following-sibling::text()[not(preceding-sibling::emphasis[@bold='yes' and text()='NOTE2:'])  and not(preceding-sibling::emphasis[@bold='yes' and text()='NOTE1:'])] | following-sibling::emphasis[not(contains(string(), 'NOTE1:'))  and  not(contains(string(), 'NOTE2:'))  and not(contains(string(), 'NOTE3:'))]"
        />
      </para>
    </note>
  </xsl:template>

  <xsl:template match="para/emphasis[position()=last() and position() > 1 and @bold='yes' and text()='NOTE3:']">
    <note>
      <para>
        <emphasis bold="yes">NOTE3:</emphasis>
        <xsl:copy-of select="following-sibling::text()[position() = 1]|following-sibling::emphasis[not(contains(string(), 'NOTE1:'))  and  not(contains(string(), 'NOTE2:'))  and not(contains(string(), 'NOTE3:'))  ]"/>
      </para>
    </note>
  </xsl:template>

</xsl:stylesheet>

电流输出:

<root>
  <para>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis> This is the text of the first note 1 <emphasis bold="yes">that should only be in the <emphasis italic="yes">first</emphasis> subsection occurance of note one.</emphasis>. This is the second sentence of the first note one. <emphasis italic="yes">Here is some other text</emphasis> that can appear. <emphasis bold="yes">Marvin Gaye is an excellent musician1.</emphasis> Play it for your girlfriend1 <emphasis italic="yes">now1.</emphasis>.
        <emphasis italic="yes">The Isley Brothers are also good.2.1</emphasis>
        <emphasis italic="yes">My girlfriend loves them1.2</emphasis>
        <emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
        <emphasis italic="yes">Steak and potatos3.2</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE2:</emphasis>
        <emphasis italic="yes">The Isley Brothers are also good.2.1</emphasis>
        <emphasis italic="yes">My girlfriend loves them1.2</emphasis>
        <emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
        <emphasis italic="yes">Steak and potatos3.2</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis>
        <emphasis italic="yes">My girlfriend loves them1.2</emphasis>
        <emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
        <emphasis italic="yes">Steak and potatos3.2</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </subsection>
    <note>
      <para>
        <emphasis bold="yes">NOTE3:</emphasis>
        <emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
        <emphasis italic="yes">Steak and potatos3.2</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </note>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis>
        <emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
        <emphasis italic="yes">Steak and potatos3.2</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </subsection>
    <note>
      <para>
        <emphasis bold="yes">NOTE3:</emphasis>
        <emphasis italic="yes">Steak and potatos3.2</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </note>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE2:</emphasis>
        <emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </subsection>
  </para>
</root>


Desired output:

<root>
  <para>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis> This is the text of the first note 1 <emphasis bold="yes">that should only be in the <emphasis italic="yes">first</emphasis> subsection occurance of note one.</emphasis>. This is the second sentence of the first note one. <emphasis italic="yes">Here is some other text</emphasis> that can appear. <emphasis bold="yes">Marvin Gaye is an excellent musician1.</emphasis> Play it for your girlfriend1 <emphasis italic="yes">now1.</emphasis>.
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE2:</emphasis>This is the text of  the first note two2.1<emphasis italic="yes">The Isley Brothers are also good.2.1</emphasis>
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis> This is the text of the second note one.1.2 <emphasis italic="yes">My girlfriend loves them1.2</emphasis>
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE3:</emphasis> This is the text of the first note three3.1.
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE1:</emphasis> This is the text of the third note one.1.3<emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis>
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE3:</emphasis> This is the text of the second note three.3.2<emphasis italic="yes">Steak and potatos3.2</emphasis>
      </para>
    </subsection>
    <subsection>
      <para>
        <emphasis bold="yes">NOTE2:</emphasis> This is the text of the second note two.2.2<emphasis italic="yes">And then some wine2.2</emphasis>
      </para>
    </subsection>
  </para>
</root>
4

1 回答 1

2

如果我正确理解您的要求,我认为您的 XSLT 可能有点过于复杂。看起来您只是想对节点进行分组,每个组的开头由带有文本状态“NOTE”的强调节点表示

假设您使用的是 XSLT 2.0(因为您当前的 XSLT 标记为 version="2.0")然后向有用的xsl:for-each-group命令打个招呼,这应该正是您所需要的。在您的情况下,以相关的强调元素开始对节点进行分组:

<xsl:for-each-group 
    select="node()" 
    group-starting-with="emphasis[starts-with(text(), 'NOTE')]">

在其中,您将输出您的subsectionpara元素,然后遍历组中的元素以复制它们

<xsl:apply-templates select="current-group()" />

您将使用XSLT 标识转换来输出强调元素本身。

这是令人愉快的短得多的 XSLT

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

   <xsl:template match="para">
      <para>
         <xsl:for-each-group select="node()" group-starting-with="emphasis[starts-with(text(), 'NOTE')]">
            <subsection>
               <para>
                  <xsl:apply-templates select="current-group()" />
               </para>
            </subsection>
         </xsl:for-each-group>
      </para>
   </xsl:template>

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

当应用于您的 XML 时,将输出以下内容

<section>
   <para>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE1:</emphasis> This is the text of the first note 1 
            <emphasis bold="yes">that should only be in the 
               <emphasis italic="yes">first</emphasis>subsection occurance of note one. 
            </emphasis>. This is the second sentence of the first note one. 
            <emphasis italic="yes">Here is some other text</emphasis>that can appear. 
            <emphasis bold="yes">Marvin Gaye is an excellent musician1.</emphasis>Play it for your girlfriend1 
            <emphasis italic="yes">now1.</emphasis>. 
         </para>
      </subsection>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE2:</emphasis>This is the text of the first note two2.1 
            <emphasis italic="yes">The Isley Brothers are also good.2.1</emphasis></para>
      </subsection>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE1:</emphasis>This is the text of the second note one.1.2 
            <emphasis italic="yes">My girlfriend loves them1.2</emphasis></para>
      </subsection>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE3:</emphasis>This is the text of the first note three3.1. </para>
      </subsection>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE1:</emphasis>This is the text of the third note one.1.3 
            <emphasis italic="yes">She is going to make me dinner tonight1.3</emphasis></para>
      </subsection>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE3:</emphasis> This is the text of the second note three.3.2 
            <emphasis italic="yes">Steak and potatos3.2</emphasis></para>
      </subsection>
      <subsection>
         <para>
            <emphasis bold="yes">NOTE2:</emphasis> This is the text of the second note two.2.2 
            <emphasis italic="yes">And then some wine2.2</emphasis></para>
      </subsection>
   </para>
</section>

有关如何在 XSLT 2.0 中分组的更多示例,请参见http://www.xml.com/lpt/a/1314

于 2013-05-10T22:35:22.590 回答