以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XSL/XSLT/XSL-FO/CSS 』  (http://bbs.xml.org.cn/list.asp?boardid=8)
----  [讨论]在xsl中一个奇怪的循环问题。。。。。  (http://bbs.xml.org.cn/dispbbs.asp?boardid=8&rootid=&id=58319)


--  作者:wangyongshan
--  发布时间:1/21/2008 5:59:00 PM

--  [讨论]在xsl中一个奇怪的循环问题。。。。。
XML文件如下:
<root>
   <clue>
         <item id="001" type="aa"/>
         <item id="002" type="bb"/>
         <http id="101" type="cc"/>

   </clue>
</root>
想转换成如下格式:
<root>
    <clue_item>
         <item_aa  id="001"/>
    </clue_item>

    <clue_item>
         <item_bb  id="002"/>
    </clue_item>

     <clue_item>
         <http_cc  id="101"/>
    </clue_item>
</root>
我的XSL如下:
<xsl:template match="/">
    <root>
        <xsl:apply-templates select="//clue"/>
   </root>
</xsl:template>

<xsl:template match="clue">
    <xsl:for-each select="./*">
          <xsl:choose>
             <xsl:when test="name()='item'">
                  <xsl:apply-templates select="//item"/>
             </xsl:when>

               <xsl:when test="name()='http'">
                  <xsl:apply-templates select="//http"/>
             </xsl:when>
         </xsl:choose>
   </xsl:for-each>
</xsl:template>

<xsl:template match="item">
    <xsl:choose>
          <xsl:when test="@type='aa'">
              <clue_item>
                  <xsl:element name="item_aa">
                     <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                  </xsl:element>
              </clue_item>
         </xsl:when>

          <xsl:when test="@type='bb'">
              <clue_item>
                  <xsl:element name="item_bb">
                     <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                  </xsl:element>
              </clue_item>
         </xsl:when>

    </xsl:choose>
</xsl:template>

<xsl:template match="http">
    <clue_item>
           <http_cc>
               <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
           </http_cc>
    </clue_item>
</xsl:template>
但是转化的结果却出现奇怪的现象:
<root>
    <clue_item>
         <item_aa  id="001"/>
    </clue_item>

    <clue_item>
         <item_bb  id="002"/>
    </clue_item>

    <clue_item>
         <item_aa  id="001"/>
    </clue_item>

    <clue_item>
         <item_bb  id="002"/>
    </clue_item>

     <clue_item>
         <http_cc  id="101"/>
    </clue_item>
</root>
红色的结果出现了重复,item怎么会循环读取2遍啊?
大家帮忙看下啊.......................


--  作者:Qr
--  发布时间:1/21/2008 8:40:00 PM

--  
不奇怪,新手总爱犯同样的低级错误,滥用“//”。item和http前不要加,如果不明白,去看一下XPath,要活学活用XSL的话很有必要。
--  作者:wangyongshan
--  发布时间:1/21/2008 9:20:00 PM

--  
呵呵,公司的需要,俺才接触xsl,一个超级菜鸟!大哥别见怪,以后要多多教教我啊。。。
最近一直在写 XML TO XML 的转换器,遇到了超多的问题。。。。哈哈
--  作者:wangyongshan
--  发布时间:1/21/2008 10:00:00 PM

--  
你好,我按照你的方法,将item 和 http前面的 // 去掉,但是转换的结果为空。
--  作者:enyaxp
--  发布时间:1/22/2008 1:26:00 AM

--  
<xsl:template match="/">
    <root>
        <xsl:apply-templates select="//clue"/>
   </root>
</xsl:template>

<xsl:template match="clue">
    <xsl:for-each select="./*">
          <xsl:choose>
             <xsl:when test="name()='item'">
                  <xsl:apply-templates select="."/> //改为“.”,代表当前节点
             </xsl:when>

               <xsl:when test="name()='http'">
                  <xsl:apply-templates select="."/> //改为“.”
             </xsl:when>
         </xsl:choose>
   </xsl:for-each>
</xsl:template>

<xsl:template match="item">
    <xsl:choose>
          <xsl:when test="@type='aa'">
              <clue_item>
                  <xsl:element name="item_aa">
                     <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                  </xsl:element>
              </clue_item>
         </xsl:when>

          <xsl:when test="@type='bb'">
              <clue_item>
                  <xsl:element name="item_bb">
                     <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                  </xsl:element>
              </clue_item>
         </xsl:when>

    </xsl:choose>
</xsl:template>

<xsl:template match="http">
    <clue_item>
           <http_cc>
               <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
           </http_cc>
    </clue_item>
</xsl:template>



--  作者:enyaxp
--  发布时间:1/22/2008 1:40:00 AM

--  
也不算低级错误啦,至少思路是对的。

只是你用<xsl:apply-templates select="//item"/>匹配模版的时候,匹配到的并不是你所想的
单个的元素 <item>,而是所有<item>元素;而且因为你有两个item,<xsl:for-each>循环的三次中有两次满足name()='item',这样也就相当于下面的两个item元素被一起扔到template中匹配两次。
         
         <item id="001" type="aa"/>
         <item id="002" type="bb"/>

这样的重复是平方级的,还好item不算多,要是有100个的话,输出中就会显示10000次item了。初学的时候出这种错很正常。


--  作者:enyaxp
--  发布时间:1/22/2008 1:47:00 AM

--  
当然这种错误其实是可以避免的,这个xsl格式还不够好,需要改进。


--  作者:wangyongshan
--  发布时间:1/22/2008 8:34:00 AM

--  
enyaxp大哥,谢谢你!最近一直在给公司写转换器,遇到了非常多的问题,我只能是一边看xsl的基础语法,一边写。
enyaxp大哥,我的那个xsl格式不够好,你能不能给点修改的建议啊,我好改进一下啊。
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
78.003ms