【问题标题】:Grouping contents of similar nodes in an XML using XSLT使用 XSLT 在 XML 中对相似节点的内容进行分组
【发布时间】:2013-01-11 06:30:46
【问题描述】:

我正在使用下面的 XML

<Root>
<sample>1</sample>
<sample>2</sample>
<sample>3</sample>
<sample>4</sample>
<sample>5</sample>
<sample>6</sample>
</Root>

我想得到下面给出的输出

<sample>123456</sample>

我正在使用下面的 XSLT 来获得上面的输出。但我得到的输出是这样的。

<sample>1</sample>
<sample>23456</sample>
<sample>2</sample>
<sample>3456</sample>
<sample>3</sample>
<sample>456</sample>
<sample>4</sample>
<sample>56</sample>
<sample>5</sample>
<sample>6</sample
><sample>6</sample>
<sample></sample>

这是我尝试过的 XSL 代码:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="sample">
<presample>
<xsl:value-of select="."/>
<xsl:variable name="code" select="following-sibling::sample" />
<xsl:for-each select="following-sibling::sample">
<xsl:if test="not(preceding-sibling::sample)">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</presample>
</xsl:template>
</xsl:stylesheet>

请帮助我更正此 XSLT 以获得上述所需的输出。

【问题讨论】:

  • user1968895,您可能对更高效的分组方法感兴趣,例如 Muenchian。

标签: xml xslt xslt-1.0


【解决方案1】:

这是怎么回事:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="sample[1]">
    <sample>
      <xsl:for-each select=". | following-sibling::sample">
        <xsl:value-of select="."/>
      </xsl:for-each>
    </sample>
  </xsl:template>

  <xsl:template match="sample[position() > 1]" />
</xsl:stylesheet>

我想你的最终目标比这更复杂,所以如果你能详细说明,可能会有更好的通用方法。

不确定这是否是您想要的,但这里有一个潜在的更通用的方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="*[text()[normalize-space(.)] and not(name(preceding-sibling::*[1]) = name())]">
    <xsl:copy>
      <xsl:variable name="list" select=". | following-sibling::*"/>
      <xsl:for-each select="$list">
        <xsl:variable name="pos" select="position()" />
        <xsl:if test="not($list[position() &lt; $pos and name() != name(current())])">
          <xsl:value-of select="."/>
        </xsl:if>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[name(preceding-sibling::*[1]) = name()]" />
  <xsl:template match="text()" />
</xsl:stylesheet>

在此运行时:

<Root>
  <sample>1</sample>
  <sample>2</sample>
  <sample>3</sample>
  <sample>4</sample>
  <sample>5</sample>
  <sample>6</sample>
  <child>
    <something>4</something>
    <something>5</something>
    <something>6</something>
    <something>7</something>
    <somethingelse>a</somethingelse>
    <somethingelse>b</somethingelse>
    <somethingelse>c</somethingelse>
    <somethingelse>d</somethingelse>
    <something>8</something>
    <something>9</something>
    <something>10</something>
  </child>
</Root>

产生这个:

<sample>123456</sample>
<something>4567</something>
<somethingelse>abcd</somethingelse>
<something>8910</something>

【讨论】:

  • 干得好@JLR :) 在短短 9 天内做出了很多贡献!
  • @InfantPro'Aravind' 谢谢!我很高兴我能够让自己变得有用。 :-)
【解决方案2】:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="sample[not(preceding-sibling::sample)]">
    <sample>
      <xsl:for-each select=". | following-sibling::sample">
        <xsl:value-of select="."/>
      </xsl:for-each>
    </sample>
  </xsl:template>

  <xsl:template match="sample[preceding-sibling::sample]" />
</xsl:stylesheet>

对于输入 XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <sample>1</sample>
  <sample>2</sample>
  <sample>3</sample>
  <sample>4</sample>
  <dummy1>a</dummy1>
  <dummy2>b</dummy2>
  <dummy3>c</dummy3>
  <dummy4>d</dummy4>
  <sample>5</sample>
  <sample>6</sample>
  <sample>7</sample>
  <sample>8</sample>
</root>

输出将是:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <sample>12345678</sample>
  <dummy1>a</dummy1>
  <dummy2>b</dummy2>
  <dummy3>c</dummy3>
  <dummy4>d</dummy4>
</root>

【讨论】:

    【解决方案3】:

    这是 Muenchian 分组方法的一个简单应用——比使用同级轴更有效的分组方法

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
     <xsl:key name="kSampleByVal" match="sample" use="."/>
    
     <xsl:template match="sample[1]" priority="2">
      <sample>
       <xsl:apply-templates select=
       "../*[generate-id()=generate-id(key('kSampleByVal',.)[1])]/text()"/>
      </sample>
     </xsl:template>
     <xsl:template match="*/*"/>
    </xsl:stylesheet>
    

    当此转换应用于以下 XML 文档时(提供的已修改以使其更具代表性):

    <Root>
        <sample>1</sample>
        <sample>2</sample>
        <sample>3</sample>
        <sample>4</sample>
        <sample>5</sample>
        <sample>6</sample>
        <sample>3</sample>
        <sample>4</sample>
        <sample>1</sample>
        <sample>2</sample>
        <sample>3</sample>
    </Root>
    

    产生想要的正确结果

    <sample>123456</sample>   
    

    请注意

    我建议在所有情况下对兄弟比较分组使用 Muenchian 分组方法。 Muenchian 具有 O(N) 时间复杂度,而兄弟比较分组的时间复杂度是二次的 - O(N ^2)。我见过兄弟比较分组需要 40 分钟,而 Muenchian 分组只需要 2 秒。

    【讨论】:

    • @IanRoberts,谢谢你告诉我——今天早上我还是有点困。固定。
    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    • 2013-08-15
    • 1970-01-01
    相关资源
    最近更新 更多