XSL合并具有相同类的相同类型的节点

时间:2018-03-27 14:40:03

标签: xml xslt xslt-2.0

我对XSL非常陌生,我试图清理一些XML以合并redondant标签(下面的示例跨度)。

<body><!-- userBodyTop goes here -->
  <div class="header" />
  <div class="document">
     <p class="text">...</p>
     <p class="Normal">
        <span class="USous-article">§ 1er </span>
        <span class="USous-article">–</span>
        <span class="USous-article"> </span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus condimentum tortor purus, ut vulputate nisl lobortis ut. Fusce luctus massa nisl, ac tincidunt eros sodales consectetur. Nulla venenatis purus non bibendum ullamcorper. In ac augue consectetur, varius massa et, interdum sem. Proin rutrum ornare ligula ac varius. Proin vitae scelerisque libero, sit amet egestas orci. Mauris pharetra consectetur efficitur. Ut commodo diam nisl, eget semper lectus commodo sed. Donec turpis diam, aliquet sed sem ac.</p>
     <p class="text>some more text</p>
  </div>
  <div class="footnotes" />
  <!-- userBodyTail goes here -->
</body>

我想要实现的目标是合并span s的课程内容&#34; USous-article&#34; :

<body><!-- userBodyTop goes here -->
  <div class="header" />
  <div class="document">
     <p class="text">...</p>
     <p class="Normal">
        <span class="USous-article">§ 1er – </span>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus condimentum tortor purus, ut vulputate nisl lobortis ut. Fusce luctus massa nisl, ac tincidunt eros sodales consectetur. Nulla venenatis purus non bibendum ullamcorper. In ac augue consectetur, varius massa et, interdum sem. Proin rutrum ornare ligula ac varius. Proin vitae scelerisque libero, sit amet egestas orci. Mauris pharetra consectetur efficitur. Ut commodo diam nisl, eget semper lectus commodo sed. Donec turpis diam, aliquet sed sem ac.</p>
     <p class="text>some more text</p>
  </div>
  <div class="footnotes" />
  <!-- userBodyTail goes here -->
</body>

我已经尝试了多种解决方案(使用前兄弟/后兄弟)和下面的XSL 2.0解决方案,我没有设法让它工作....

<xsl:template match="p[@class='Normal'][count(./span[@class='USous-article'])>0]">
<xsl:copy>
  <xsl:for-each-group select="node() except text()[not(normalize-space())]" group-adjacent="boolean(self::*)">
    <xsl:choose>
      <xsl:when test="current-grouping-key()">
        <xsl:for-each-group select="current-group()" group-by="concat(node-name(.), '|', @class)">
          <xsl:element name="{name()}" namespace="{namespace-uri()}">
            <xsl:copy-of select="@class" />
            <xsl:apply-templates select="current-group()/node()" />
          </xsl:element>
        </xsl:for-each-group>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="current-group()" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each-group>
</xsl:copy>
</xsl:template>

有什么想法吗?我没有线索......

1 个答案:

答案 0 :(得分:1)

尝试以下脚本:

<?xml version="1.0" encoding="UTF-8"?>
<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:preserve-space elements="span"/>

  <xsl:template match="p[@class='Normal']">
    <p>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="*" group-adjacent="concat(name(), '/',  @class)">
        <xsl:element name="{name()}">
          <xsl:attribute name="class" select="@class"/>
          <xsl:value-of select="current-group()/text()"/>
        </xsl:element>
      </xsl:for-each-group>
      <xsl:value-of select="text()"/>
    </p>
  </xsl:template>

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

请注意模板匹配p中的操作顺序:

  • 复制p元素。
  • 将模板应用于属性。
  • 对于具有相同名称和类的每组相邻节点:
    • 复制元素。
    • 复制类属性。
  • 复制当前元素的文本。

需要注意的另一个要点是使用strip-spacepreserve-space 命令:

  • 从所有标签中剥离空间。
  • span标签除外,为其保留空格。

否则,最后一个span元素的空格 - 内容将丢失。