xslt: 这个目的怎么实现?

Magicloud 2003-08-26 07:48:14
<x y = "1" z = "1" />
<x y = "1" z = "2" />
<x y = "2" z = "1" />
<x y = "2" z = "2" />

转换为:

<y no = "1">
<z no = "1" />
<z no = "2" />
</y>
<y no = "2">
<z no = "1" />
<z no = "2" />
</y>

谢谢。

我想到的方法是:读每个x时,判断其y属性值是否与前一个x的y相同,但我觉得这样效率会很低。
...全文
45 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
saucer 2003-09-01
  • 打赏
  • 举报
回复
there is probably no better method with XSLT, if I were you, I would write a simple program using either push or pull stream-based XML parser to do the conversion manually
Magicloud 2003-09-01
  • 打赏
  • 举报
回复
.
Magicloud 2003-09-01
  • 打赏
  • 举报
回复
搞清楚了,效率低的不是这段代码,而是xmlspy的内置引擎,调试版的东西就是慢。
aspx执行这段代码,只要10秒,可以接受。
Magicloud 2003-08-31
  • 打赏
  • 举报
回复
唉,这段代码太消耗资源了,xmlspy被弄死了无数次……
原数据文件有198k之大,每项7个属性,要做5层嵌套的……
生成xml时,数据已排序,即:select ... order by a, b, c, d, e, f,生成:<row a b c d e f g h/>
是否有优化的代码?或针对已排序的情况,有更快速的实现?
saucer 2003-08-29
  • 打赏
  • 举报
回复
how many attributes do you have?

is there a general solution? maybe, but I would guess that will involve a lot of recursive template calls and very tedious to do

if you just have a few attributes, try something like

1.xml:
<?xml-stylesheet type="text/xsl" href="a.xsl" ?>
<root>
<x y = "1" z = "1" w="1"/>
<x y = "1" z = "2" w="2"/>
<x y = "2" z = "1" w="1"/>
<x y = "2" z = "2" w="2"/>
<x y = "2" z = "1" w="1"/>
<x y = "3" z = "2" w="3"/>
<x y = "1" z = "1" w="1"/>
<x y = "1" z = "2" w="3"/>
</root>


1.xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="y2x" match="x" use="@y" />
<xsl:key name="yw2x" match="x" use="concat(@y,'#',@z)" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="x[count(. | key('y2x',@y)[1]) = 1]">
<y no="{@y}">
<xsl:for-each select="key('y2x',@y)[count(. | key('yw2x',concat(@y,'#',@z))[1])=1]">
<z no="{@z}">
<xsl:for-each select="key('yw2x',concat(@y,'#',@z))">
<w no="{@w}" />
</xsl:for-each>
</z>
</xsl:for-each>
</y>
</xsl:for-each>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
Magicloud 2003-08-28
  • 打赏
  • 举报
回复
我的意思是变成这样的:
<y no = "1">
<z no = "1">
<w no = "1"/>
<w no = "2"/>
</z>
<z no = "2">
<w no = "1"/>
<w no = "2"/>
</z>
</y>

我觉得应该可以用一个模板递归实现,但我写的就是不匹配……再次烦请指教。
saucer 2003-08-27
  • 打赏
  • 举报
回复
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="y2x" match="x" use="@y" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="x[count(. | key('y2x',@y)[1]) = 1]">
<y no="{@y}">
<xsl:for-each select="key('y2x',@y)">
<xsl:call-template name="genTree">
<xsl:with-param name="nodelist" select="@*[name() != 'y']" />
</xsl:call-template>
</xsl:for-each>
</y>
</xsl:for-each>
</xsl:copy>
</xsl:template>

<xsl:template name="genTree">
<xsl:param name="nodelist" />
<xsl:if test="$nodelist">
<xsl:element name="{name($nodelist[1])}">
<xsl:attribute name="no"><xsl:value-of select="$nodelist[1]" /></xsl:attribute>
<xsl:call-template name="genTree">
<xsl:with-param name="nodelist" select="$nodelist[position() > 1]" />
</xsl:call-template>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Magicloud 2003-08-27
  • 打赏
  • 举报
回复
我的意思是说:
<x y = "1" z = "1" w = "1">
这样的,转换为:
<y no = "1">
<z no = "1">
<w no = "1">
</w>
</z>
</y>
谢谢。
saucer 2003-08-27
  • 打赏
  • 举报
回复
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="y2x" match="x" use="@y" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="x[count(. | key('y2x',@y)[1]) = 1]">
<y no="{@y}">
<xsl:for-each select="key('y2x',@y)">
<xsl:for-each select="@*[name() != 'y']">
<xsl:element name="{name()}">
<xsl:attribute name="no"><xsl:value-of select="." /></xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</y>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
saucer 2003-08-27
  • 打赏
  • 举报
回复
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="y2x" match="x" use="@y" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="x[count(. | key('y2x',@y)[1]) = 1]">
<y no="{@y}">
<xsl:for-each select="key('y2x',@y)">
<xsl:for-each select="@*[name() != 'y']">
<xsl:element name="{name()}">
<xsl:attribute name="no"><xsl:value-of select="." /></xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</y>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Magicloud 2003-08-27
  • 打赏
  • 举报
回复
还有一个问题:如果不只是三层树,比如z后边还有个w,该怎么做?
我觉得应该是把z的for-each换成类似结构的嵌套,但我改的结果都是xpath表达式不正确。
还请指教。
saucer 2003-08-26
  • 打赏
  • 举报
回复
assume your xml is

<root>
<x y = "1" z = "1" />
<x y = "1" z = "2" />
<x y = "2" z = "1" />
<x y = "2" z = "2" />
</root>
saucer 2003-08-26
  • 打赏
  • 举报
回复
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="y2x" match="x" use="@y" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="x[count(. | key('y2x',@y)[1]) = 1]">
<y no="{@y}">
<xsl:for-each select="key('y2x',@y)">
<z no="{@z}" />
</xsl:for-each>
</y>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
saucer 2003-08-26
  • 打赏
  • 举报
回复
use xsl:key and the Muenchian Method , see

http://www.jenitennison.com/xslt/grouping/muenchian.html

8,909

社区成员

发帖
与我相关
我的任务
社区描述
XML/XSL相关问题讨论专区
社区管理员
  • XML/XSL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧