处理兄弟节点并标记为已处理

时间:2016-06-20 17:02:37

标签: xml xslt

实际上我遇到的问题是用以下条件解析我的XML元素;   - 总列数为4,如果元素节点的总hspan变为4,则将其视为一行。例如,元素1,2作为行AND 3,4作为行AND 5也应该被视为行。

<elements cols="4">
<element hspan="1" text= "text1"/>
<element hspan="3" text= "text2"/>
<element hspan="2" text= "text3"/>
<element hspan="2" text= "text4"/>
<element hspan="4" text= "text5"/>
</elements>

有时元素没有hspan,在这种情况下,元素应该被视为1并继续进行。

<elements cols="4">
<element text= "text1"/>
<element hspan="3" text= "text2"/>
<element hspan="2" text= "text3"/>
<element hspan="2" text= "text4"/>
<element hspan="4" text= "text5"/>
</elements>

如果我在我的xslt中创建循环以获取下一个兄弟节点,我该如何忽略已处理的元素。

预期结果是;

<row>
  <cells>
        <label text = text1>
        <label text = text2>
  </cells>
</row>
<row>
 <cells>
       <label text = text3>
       <label text = text4>
 </cells>
</row>
<row>
 <cells>
       <label text = text5>
 </cells>
</row>

注意:我使用的是XSLT 2.0。 我非常感谢任何帮助。 问候, Jaji

1 个答案:

答案 0 :(得分:1)

假设所有相关@hspan属性的计数总是完全符合所需cols的数量,您可以将元素分组如下:

<xsl:for-each-group select="element" group-starting-with="*[sum(preceding-sibling::element/@hspan) mod $cols = 0]">

即。对前面的元素求和,并且总和除以精确的4,然后这表示一个新行。

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="elements">
    <xsl:variable name="cols" select="@cols" />
    <xsl:for-each-group select="element" group-starting-with="*[sum(preceding-sibling::element/@hspan) mod $cols = 0]">
      <row>
        <cells>
           <xsl:apply-templates select="current-group()" />
        </cells>
      </row>
    </xsl:for-each-group> 
  </xsl:template>

  <xsl:template match="element">
     <label text="{@text}" />
  </xsl:template>
</xsl:stylesheet>

当然,如果cols设置为“4”并且前两个元素的hspan属性为2和3,则会失败。

编辑:在回复评论时,如果某些element元素没有hspan属性,那么您的XSLT将如下所示(感谢Martin Honnen!)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
   xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="elements">
    <xsl:variable name="cols" select="@cols" />
    <xsl:for-each-group select="element" group-starting-with="*[sum(preceding-sibling::element/xs:decimal((@hspan,1)[1])) mod $cols = 0]">
      <row>
        <cells>
           <xsl:apply-templates select="current-group()" />
        </cells>
      </row>
    </xsl:for-each-group> 
  </xsl:template>

  <xsl:template match="element">
     <label text="{@text}" />
  </xsl:template>
</xsl:stylesheet>