以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XSL/XSLT/XSL-FO/CSS 』  (http://bbs.xml.org.cn/list.asp?boardid=8)
----  [求助]xslt同一文件二次遍历问题  (http://bbs.xml.org.cn/dispbbs.asp?boardid=8&rootid=&id=78065)


--  作者:clement1986
--  发布时间:11/2/2009 3:57:00 PM

--  [求助]xslt同一文件二次遍历问题
<databox>
<ABC>
<ZZ value="1"/>
<Structure>
<ZZ value="3"/>
</Structure>
<Structure>
<ZZ value="2"/>
</Structure>
</ABC>

<ABC>
<ZZ value="2"/>
<Structure>
<ZZ value="3"/>
</Structure>
<Structure>
<ZZ value="1"/>
</Structure>
</ABC>

<ABC>
<ZZ value="4"/>
<Structure>
<ZZ value="3"/>
</Structure>
<Structure>
<ZZ value="2"/>
</Structure>
</ABC>

</databox>

逻辑是这样的:需要依据<ABC>直接子元素ZZ的值(即不考虑在Structure标签下的ZZ值)来作为筛选条件,这里符合条件的ZZ是1,2,4.
然后通过xslt生成目标xml文件时,需要在Structure上设置过滤,即Structure标签下的ZZ的值如果在上述1,2,4之中,那么就保留该Strucuture的内容。否则过滤掉该Structure内容。

转换后的xml如下:

<databox>
<ABC>
<ZZ value="1"/>

<Structure>
<ZZ value="2"/>
</Structure>
</ABC>

<ABC>
<ZZ value="2"/>

<Structure>
<ZZ value="1"/>
</Structure>
</ABC>

<ABC>
<ZZ value="4"/>

<Structure>
<ZZ value="2"/>
</Structure>
</ABC>

</databox>

这个感觉有点难度啊,需要首先遍历ABC下的ZZ值并保存,然后在每个Structure时将Structure下的ZZ值和上述保存的值比对,不知道这个xsl该怎么实现,呼唤达人啊


--  作者:Qr
--  发布时间:11/2/2009 9:32:00 PM

--  
<xsl:template match="/">
  <databox>
  <xsl:for-each select="//ABC/ZZ">
    <xsl:variable name="zz" select="@value"/>
    <xsl:for-each select="//Structure">
      <xsl:if test="$zz=ZZ/@value">
        <ABC>
          <xsl:copy-of select="current()/preceding-sibling::ZZ[1]"/>
          <xsl:copy-of select="current()"/>
        </ABC>
      </xsl:if>  
    </xsl:for-each>
  </xsl:for-each>
  </databox>
</xsl:template>
以上代码只针对你的这个特定的XML文档,结果如你所愿。但是,XML格式有变,比如第一个ABC中有两个符合条件的Structure,结果就不同了。所以说,此段代码只起一个引导性作用,而不是通用性强的代码。


--  作者:Qr
--  发布时间:11/2/2009 9:46:00 PM

--  
本代码的关键和难点:
1、current() -- XSL
2、preceding-sibling -- XPath


--  作者:clement1986
--  发布时间:11/2/2009 10:52:00 PM

--  
谢谢版主,我给出的是个示例文件,可能存在多个structure的,你的方法我还没实验,不过我看得懂你的意思,应该是可行的。我刚刚写出了可行的xsl,这里把关键贴出来(ABC,ZZ都是代称,下面代码用的是我时间文件中的名字)

首先定义一个全局变量<xsl:variable name="testt" select="(//ABC)"/>获取ABC列表

在Structure模版中加入如下:
<xsl:param name="current" select="ZZ//@value"/>   <!--取得当前structure中的ZZ-->
<xsl:for-each select="(//ABC)">                              <!--取得ABC列表-->
<xsl:if test="$current=ZZ//@value">           <!--将当前ZZ和ABC列表的ZZ值依次比较,如果存在则实现需要的逻辑-->
.....
.....
</xsl:if>
</xsl:for-each>


--  作者:Qr
--  发布时间:11/2/2009 11:09:00 PM

--  
我也用类似的方法,通过3个for-each嵌套13行代码解决了存在多个structure的问题。

不过,既然你已经做出来,我就不贴代码了。思路还是2楼的,稍作改动即可实现。

你的需求挺有意思的,有一定的难度和挑战性,所以,我才有继续完善代码的意愿,否则,用贴在2楼的代码就打发过去了。呵呵。


--  作者:clement1986
--  发布时间:11/3/2009 7:58:00 PM

--  
呵呵,不能碰到一个问题解决一个,要从一个问题中去发现别的新知识~thanks anyway
--  作者:疯车车
--  发布时间:12/26/2009 8:48:00 AM

--  
好东西,支持一下。新来的。。。
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
62.500ms