Объединить соседние узлы и сестры с XSLT - PullRequest
4 голосов
/ 19 января 2010

У меня есть вопрос, который вызвал у меня ужасную головную боль. Пожалуйста, помогите мне. Ввод:

<body>
 <p class="section"> section 1 </p>
 <p class="code"> some code </p>
 <p class="code"> following code </p>
 <p class="code"> following code </p>
 <p class="section"> section 2 </p>
 <p class="code"> other code </p>
 <p class="code"> following code </p>
 <p class="code"> following code </p>
 <p class="section"> section 3 </p>
 <p class="code"> still other code </p>
 <p class="code"> following </p>
 <p class="code"> following </p>
</body>

Вывод, который я хотел бы:

<code><body>
 <p class="section"> section 1 </p>
 <pre> some code following code following code 

раздел 2

 other code following code following code 

раздел 3

 still other code following following 

Проблема состоит в том, чтобы свернуть в тег <pre> все соседние теги <p class="code">. Не найти способ сделать это с помощью XSLT. Как вы думаете, решение существует?

Ответы [ 4 ]

4 голосов
/ 19 января 2010

Вам не нужно перестраивать свой XML, посмотрите здесь: XSLT Grouping Siblings .

3 голосов
/ 19 января 2010

С XSLT 2.0 вы можете использовать для каждой группы смежных групп следующим образом:

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

  <xsl:output indent="yes"/>

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

  <xsl:template match="body">
    <xsl:copy>
      <xsl:for-each-group select="*" group-adjacent="boolean(self::p[@class = 'code'])">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <pre>
              <xsl:apply-templates select="current-group()/node()"/>
            

Вы можете использовать XSLT 2.0 с Saxon 9 или с AltovaXML tools .

2 голосов
/ 19 января 2010

Примерно так должно работать:

<code><xsl:template match="body">
    <xsl:apply-templates select="p[@class='section']" />
</xsl:template>

<xsl:template match="p[@class='section']">
    <xsl:copy-of select="."/>
    <pre>
        <xsl:variable name="code" select="following-sibling::p[@class='code']" />
        <xsl:for-each select="following-sibling::p">
            <xsl:variable name="index" select="position()"/>
            <xsl:if test="generate-id(.)=generate-id($code[$index])">
                <xsl:value-of select="."/>
            </xsl:if>
        </xsl:for-each>
    
</ XSL: шаблон>
0 голосов
/ 19 января 2010

Проблема в том, что ваш XML недостаточно структурирован для простого решения XSLT.

Различные "разделы" на самом деле не настроены так, чтобы их было легко извлечь.Если у вас есть контроль над входным XML, посмотрите, можете ли вы изменить его на что-то вроде этого:

<body>
 <p class="section"> section 1 
  <p class="code"> some code </p>
  <p class="code"> following code </p>
  <p class="code"> following code </p>
 </p>
 <p class="section"> section 2
  <p class="code"> other code </p>
  <p class="code"> following code </p>
  <p class="code"> following code </p>
 </p>
 <p class="section"> section 3
  <p class="code"> still other code </p>
  <p class="code"> following </p>
  <p class="code"> following </p>
 </p>
</body>

Это позволит вам определить xsl-template для "секции", в которой вы можете xsl-foreach более«кодовые» классы.

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