在这种情况下如何获取节点

时间:2013-05-14 13:51:11

标签: xslt xpath xslt-2.0

我正在使用xslt 2.0,我有以下示例xml,我想得到两个“header-grey”节点之间的所有“header-lightgray”节点,这里的问题是:我不知道有多少“标题-lightgray“那里。所以我不能使用position()函数。并且每个xsl都不支持break。

<t>
<parent class="header-gray"></parent>
<parent class="header-lightgray"></parent>
<parent class="header-lightgray"></parent>
<parent class="header-lightgray"></parent>
...
<parent class="header-gray"></parent>
<parent class="header-lightgray"></parent>
<parent class="header-lightgray"></parent>
<parent class="header-lightgray"></parent>
<parent class="header-gray"></parent>
</t>

我想通过它们来替换所有节点,header-grey with div和header-lightgray with span。预期的输出是:

<div class="header-gray">
<span class="header-lightgray"/>
<span class="header-lightgray"/>
<span class="header-lightgray"/>
...
</div>
<div class="header-gray">
<span class="header-lightgray"/>
<span class="header-lightgray"/>
<span class="header-lightgray"/>
</div>

那怎么办呢?

感谢任何帮助。

解决方案我想根据Jan Vlcinsky的回答分享:

<xsl:for-each select="/t/parent[@class='header-gray']">
  <xsl:variable name="ns1" select="current()/following-sibling::parent"/>
  <xsl:variable name="ns2" select="current()/following-sibling::parent[@class='header-gray'][1]/preceding-sibling::parent"/>
  <div class="header-gray">
  <xsl:for-each select="$ns1[count(.| $ns2)=count($ns2)]">
     <span class="header-lightgray"/>      
  </xsl:for-each>
  </div>
</xsl:for-each>

我不验证上面的代码,但它在我的实际代码中是相同的逻辑。 我没有使用xslt 2.0方式,因为我发现我使用的lxml 2.3不支持xslt 2.

3 个答案:

答案 0 :(得分:0)

请参阅页面http://gandhimukul.tripod.com/xslt/grouping20.html

底部的“3.位置分组问题”部分

您的问题似乎有点重复:How would you find all nodes between two H3's using XPATH?

问题XPath : select all following siblings until another sibling也处理同样的问题。

答案 1 :(得分:0)

此转化

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <t>
   <xsl:for-each-group select="*"
        group-starting-with="parent[@class='header-gray']">
     <div class="header-gray">
       <xsl:apply-templates select="current-group()[position() ne 1]"/>
     </div>
   </xsl:for-each-group>
  </t>
 </xsl:template>

 <xsl:template match="parent">
   <span class="{@class}"/>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(提供的片段,包装到单个顶部元素中,使其成为格式良好的XML文档):

<t>
    <parent class="header-gray"></parent>
    <parent class="header-lightgray"></parent>
    <parent class="header-lightgray"></parent>
    <parent class="header-lightgray"></parent>
    <parent class="header-gray"></parent>
    <parent class="header-lightgray"></parent>
    <parent class="header-lightgray"></parent>
    <parent class="header-lightgray"></parent>
    <parent class="header-gray"></parent>
</t>

会产生想要的正确结果:

<t>
   <div class="header-gray">
      <span class="header-lightgray"/>
      <span class="header-lightgray"/>
      <span class="header-lightgray"/>
   </div>
   <div class="header-gray">
      <span class="header-lightgray"/>
      <span class="header-lightgray"/>
      <span class="header-lightgray"/>
   </div>
   <div class="header-gray"/>
</t>

答案 2 :(得分:-1)

这是一种方法。

当这个XSLT 2.0解决方案:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="/*">
      <t>
         <xsl:apply-templates
           select="parent[@class = 'header-gray'][following-sibling::*]"/>
      </t>
   </xsl:template>

   <xsl:template match="*[@class = 'header-gray']">
      <div class="{@class}">
         <xsl:apply-templates
           select="
             following-sibling::*[@class = 'header-lightgray'] 
               intersect
             following-sibling::*[@class = 'header-gray'][1]/
                 preceding-sibling::*[@class = 'header-lightgray']"/>
      </div>
   </xsl:template>

   <xsl:template match="*[@class = 'header-lightgray']">
      <span class="{@class}"/>
   </xsl:template>

</xsl:stylesheet>

...应用于提供的XML(包装在顶级元素中以使文档格式正确):

<t>
  <parent class="header-gray"/>
  <parent class="header-lightgray"/>
  <parent class="header-lightgray"/>
  <parent class="header-lightgray"/>
  <parent class="header-gray"/>
  <parent class="header-lightgray"/>
  <parent class="header-lightgray"/>
  <parent class="header-lightgray"/>
  <parent class="header-gray"/>
</t>

...产生了所需的结果:

<t>
  <div class="header-gray">
    <span class="header-lightgray" />
    <span class="header-lightgray" />
    <span class="header-lightgray" />
  </div>
  <div class="header-gray">
    <span class="header-lightgray" />
    <span class="header-lightgray" />
    <span class="header-lightgray" />
  </div>
</t>

此解决方案使用XPath 2.0's intersect operation