难题:如何将名称空间格式的字符串分组转为树型

wangwenyou 2003-12-18 11:10:04

<Node name ="java.util.Date"/>
<Node name ="java.util.Map"/>
<Node name ="java.io.Reader"/>
<Node name ="java.io.Write"/>
期待结果
<Node name="java">
<Node name ="util">
<Node name ="Date"/>
<Node name ="Map"/>
</Node>
<Node name ="io">
<Node name ="Reader"/>
<Node name ="Write"/>
</Node>
</Node>

敬请各位解决,谢谢了:)
...全文
107 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangwenyou 2003-12-19
  • 打赏
  • 举报
回复
用受限的逻辑完成复杂的任务,才是大脑最好的运动:)
saucer 2003-12-19
  • 打赏
  • 举报
回复
>>>XSLT就没有解决不了的问题

not true, XSLT is very limited
wangwenyou 2003-12-19
  • 打赏
  • 举报
回复
是这样的,其实应用里也不会无限增加级次
但我只是把它作为一个题目,我自己没做出来,所以期待完满的解决方案

其实只要有一次中间转换,问题会变得很简单,但使用了nodeset,就变得很不那么让人舒服了。我目前的解决是为避免RTF,用程序生成中间结果,再使用XSLT,但一致心有不甘,因为我相信,只要我们敢想,XSLT就没有解决不了的问题。
saucer 2003-12-19
  • 打赏
  • 举报
回复
you can try to add more keys

<xsl:key name="n4" match="Node" use="..." />
<xsl:key name="n5" match="Node" use="..." />
...

but like I said earlier, it is not very scalable
wangwenyou 2003-12-19
  • 打赏
  • 举报
回复
呵呵,谢谢思归
很好的解决,但限定了级次:(
saucer 2003-12-19
  • 打赏
  • 举报
回复
try to use <xsl:key>, it is not very scalable, but try the following stylesheet (没怎么试过,所以也许并不完全正确):

TestNode.xml:
<?xml-stylesheet type="text/xsl" href="TestNode.xsl" ?>
<Nodes>
<Node name ="java.util.Date"/>
<Node name ="java.util.Map"/>
<Node name ="java.io.Reader"/>
<Node name ="java.io.Write"/>
</Nodes>

TestNode.xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="n1" match="Node" use="substring-before(@name,'.')" />
<xsl:key name="n2" match="Node" use="concat(substring-before(@name,'.'), '.', substring-before(substring-after(@name,'.'),'.'))" />
<xsl:key name="n3" match="Node" use="concat(substring-before(@name,'.'), '.', substring-before(substring-after(@name,'.'),'.'),'.', substring-after(substring-after(@name,'.'),'.'))" />
<xsl:key name="n4" match="Node" use="dummykey" />

<xsl:template match="Nodes">
<xsl:copy>
<xsl:apply-templates select="Node[count(. | key('n1',substring-before(@name,'.'))[1]) =1]">
<xsl:with-param name="level" select="1" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="Node">
<xsl:param name="level"/>
<xsl:param name="length" select="0" />
<xsl:if test="string-length(@name) > $length">
<xsl:copy>
<xsl:variable name="key">
<xsl:call-template name="getKey">
<xsl:with-param name="length" select="$length" />
<xsl:with-param name="name" select="@name" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="$key != ''">
<xsl:choose>
<xsl:when test="$length = 0">
<xsl:attribute name="name"><xsl:value-of select="$key" /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="name"><xsl:value-of select="substring($key,$length+2)" /></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="//Node[starts-with(@name,$key) and count(. | key(concat('n', $level + 1), concat($key, '.', substring-before(substring(@name, string-length($key)+2),'.')))[1]) =1]">
<xsl:with-param name="level" select="$level + 1" />
<xsl:with-param name="length" select="string-length($key)" />
</xsl:apply-templates>
</xsl:if>
</xsl:copy>
</xsl:if>
</xsl:template>

<xsl:template name="getKey">
<xsl:param name="length"/>
<xsl:param name="name"/>
<xsl:choose>
<xsl:when test="$length = 0">
<xsl:choose>
<xsl:when test="contains($name,'.')">
<xsl:value-of select="substring-before($name,'.')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$name" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:if test="string-length($name) > $length">
<xsl:choose>
<xsl:when test="contains(substring($name, $length+2),'.')">
<xsl:value-of select="concat(substring($name,1,$length), '.', substring-before(substring($name, $length+2),'.'))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$name" />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
wangwenyou 2003-12-18
  • 打赏
  • 举报
回复
这个问题是我在实际应用中遇到的,我先进行了一次转换,把它转换成为形如
<Node>
<field>java</field>
<field>util</field>
<field>Date</field>
<Node>
的RTF,赋给一个variable,但不用nodeset(),无法使用XPath访问RTF。
我不希望牺牲可扩展性,所以这成了一个难题。后来我使用程序方法解决了,但一直心有不甘,希望看到不使用nodeset的XSLT的解决方案。


wangwenyou 2003-12-18
  • 打赏
  • 举报
回复
呵呵,不妨试一试
您所说的那几个函数只能走一两步
待接入自我 2003-12-18
  • 打赏
  • 举报
回复
个人感觉没有那么复杂,使用好字符串函数
substring-before,substring-after,contains,starts-with
这几个函数,完全可以通过循环实现

8,909

社区成员

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

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