Как перебрать предшествующих братьев и сестер до точки - PullRequest
3 голосов
/ 16 сентября 2011

У меня есть этот XML:

<p>
    <span>Foo</span>
    <br/>
</p>

<p>
    <span>Foo</span>
    <br/>
    <span>Foo</span>
    <span>Foo</span>
    <br/>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
    <br/>
    <span>Foo</span>
    <span>Foo</span>
    <span>Foo</span>
    <br/>
</p>

Я бы хотел сначала выбрать тег <br/>, а затем перебрать пролеты над ними. Причина этого заключается в том, чтобы избавиться от тегов <br/> и заменить тегами <p></p>, как показано ниже:

<p>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
    <span>Foo</span>
</p>

Это разновидность xslt, которую я придумал:

<xsl:template match="br">
    <p>
    <xsl:for-each select="preceding-sibling::span">
         <span>
         <xsl:value-of select="." />
         </span>
    </xsl:for-each>
    </p>
</xsl:template>

Я знаю, что это неправильно, так как он выберет все промежутки внутри тега P, а не только те, что были перед предыдущим тегом br. Любые предложения по достоинству оценены большое спасибо заранее

1 Ответ

3 голосов
/ 16 сентября 2011

Одним из способов достижения этого является использование клавиши для соответствия всем span , которые предшествуют данному br тегу

<xsl:key name="para" match="span" use="generate-id(following-sibling::br[1])" />

т.е. сгруппировать все теги span по первым br , следующим за ними.

Затем вы можете сопоставить элементы br ииспользуйте этот ключ, чтобы получить все ассоциированные span предшествующие ему теги

<xsl:template match="br">
   <p>
      <xsl:apply-templates select="key('para', generate-id())" />
   </p>

Вот полный XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>

   <xsl:key name="para" match="span" use="generate-id(following-sibling::br[1])" />

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

   <xsl:template match="p">
      <xsl:apply-templates select="br" />
      <xsl:if test="span[not(following-sibling::br)]">
         <p>
            <xsl:apply-templates select="span[not(following-sibling::br)]" />
         </p>
      </xsl:if>
   </xsl:template>

   <xsl:template match="br">
      <p>
         <xsl:apply-templates select="key('para', generate-id())" />
      </p>
   </xsl:template>

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

</xsl:stylesheet>

Когдаприменяется к следующему входному XML (я предполагаю, что ваш образец заключен в тег body , чтобы сделать его действительным XML

<body>
   <p>
      <span>Foo 1</span>
      <br/>
   </p>
   <p>
      <span>Foo 2</span>
      <br/>
      <span>Foo 3</span>
      <span>Foo 4</span>
      <br/>
   </p>
   <p>
      <span>Foo 5</span>
      <span>Foo 6</span>
      <br/>
      <span>Foo 7</span>
      <span>Foo 8</span>
      <span>Foo 9</span>
      <br/>
      <span>Foo 10</span>
   </p>
</body>

Выводится следующее:

<body>
   <p>
      <span>Foo 1</span>
   </p>
   <p>
      <span>Foo 2</span>
   </p>
   <p>
      <span>Foo 3</span>
      <span>Foo 4</span>
   </p>
   <p>
      <span>Foo 5</span>
      <span>Foo 6</span>
   </p>
   <p>
      <span>Foo 7</span>
      <span>Foo 8</span>
      <span>Foo 9</span>
   </p>
   <p>
      <span>Foo 10</span>
   </p>
</body>

Обратите внимание, что в качестве примера я добавил случай, чтобы справиться с тегами span , которые не имеют следующих тегов br в абзаце.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...