从 xsl 输出中删除重复节点
给定以下 Xml:
<record>
<category>Sport/Racket Sports/Tennis</category>
<category>Sport/Racket Sports/Badminton</category>
</record>
我正在尝试分解类别,以便生成以下 Xml:
<add>
<doc>
<field name="category_0">Sport</field>
<field name="category_1">Sport/Racket Sports</field>
<field name="category_2">Sport/Racket Sports/Tennis</field>
<field name="category_2">Sport/Racket Sports/Badminton</field>
</doc>
</add>
我已经设法生成了几乎就在那里的东西..我现在需要一种删除重复项的方法?有什么想法吗?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="record">
<add>
<doc>
<xsl:for-each select="category[. != '']">
<xsl:call-template name="split-cats">
<xsl:with-param name="prefix" select="''"/>
<xsl:with-param name="text" select="."/>
<xsl:with-param name="level" select="number(0)"/>
</xsl:call-template>
</xsl:for-each>
</doc>
</add>
</xsl:template>
<xsl:template name="split-cats">
<xsl:param name="text" select="."/>
<xsl:param name="prefix"/>
<xsl:param name="level" select="0"/>
<xsl:choose>
<xsl:when test="contains($text, '/')">
<field>
<xsl:attribute name="name">
<xsl:text>category_</xsl:text><xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:value-of select="concat($prefix, substring-before($text, '/'))"/>
</field>
<xsl:call-template name="split-cats">
<xsl:with-param name="prefix" select="concat($prefix, concat(substring-before($text, '/'), '/'))"/>
<xsl:with-param name="text" select="substring-after($text, '/')"/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<field>
<xsl:attribute name="name">
<xsl:text>category_</xsl:text><xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:value-of select="concat($prefix, $text)"/>
</field>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
此模板生成:
<add>
<doc>
<field name="category_0">Sport</field>
<field name="category_1">Sport/Racket Sports</field>
<field name="category_2">Sport/Racket Sports/Tennis</field>
<field name="category_0">Sport</field>
<field name="category_1">Sport/Racket Sports</field>
<field name="category_2">Sport/Racket Sports/Badminton</field>
</doc>
</add>
如您所见,其中有两次 Sport
和 Sport/Racket Sports
:(
仅供参考:我需要能够使用 XSLT 1.0 来完成此操作,
谢谢
Dave
Given the following Xml:
<record>
<category>Sport/Racket Sports/Tennis</category>
<category>Sport/Racket Sports/Badminton</category>
</record>
I'm trying to break up the categories so that the following Xml is produced:
<add>
<doc>
<field name="category_0">Sport</field>
<field name="category_1">Sport/Racket Sports</field>
<field name="category_2">Sport/Racket Sports/Tennis</field>
<field name="category_2">Sport/Racket Sports/Badminton</field>
</doc>
</add>
I've managed to produce something which is nearly there.. I now need a way of removing the duplicates? Any ideas?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="record">
<add>
<doc>
<xsl:for-each select="category[. != '']">
<xsl:call-template name="split-cats">
<xsl:with-param name="prefix" select="''"/>
<xsl:with-param name="text" select="."/>
<xsl:with-param name="level" select="number(0)"/>
</xsl:call-template>
</xsl:for-each>
</doc>
</add>
</xsl:template>
<xsl:template name="split-cats">
<xsl:param name="text" select="."/>
<xsl:param name="prefix"/>
<xsl:param name="level" select="0"/>
<xsl:choose>
<xsl:when test="contains($text, '/')">
<field>
<xsl:attribute name="name">
<xsl:text>category_</xsl:text><xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:value-of select="concat($prefix, substring-before($text, '/'))"/>
</field>
<xsl:call-template name="split-cats">
<xsl:with-param name="prefix" select="concat($prefix, concat(substring-before($text, '/'), '/'))"/>
<xsl:with-param name="text" select="substring-after($text, '/')"/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<field>
<xsl:attribute name="name">
<xsl:text>category_</xsl:text><xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:value-of select="concat($prefix, $text)"/>
</field>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This template produces:
<add>
<doc>
<field name="category_0">Sport</field>
<field name="category_1">Sport/Racket Sports</field>
<field name="category_2">Sport/Racket Sports/Tennis</field>
<field name="category_0">Sport</field>
<field name="category_1">Sport/Racket Sports</field>
<field name="category_2">Sport/Racket Sports/Badminton</field>
</doc>
</add>
Which as you can see has Sport
and Sport/Racket Sports
in there twice :(
FYI: I need to be able to do this using XSLT 1.0
Thanks
Dave
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是一种直接的方法,只需在代码创建的结果上使用 Muenchian 分组插入第二个转换步骤:
这会使用
exsl:node-set
但是,如果您在浏览器中以 XSLT 1.0 为目标那么对于 IE/MSXML,您需要使用 中显示的脚本修复它http://dpcarlisle.blogspot.com/2007/05/exslt-node-set-function.html。Here is a straight-forward approach that simply inserts a second transformation step using Muenchian grouping on the result your code creates:
That makes use of
exsl:node-set
however, if you target XSLT 1.0 in the browsers then for IE/MSXML you need to fix it with the script shown in http://dpcarlisle.blogspot.com/2007/05/exslt-node-set-function.html.另一种不使用扩展函数(但不一定像使用 Muenchian 分组那样有效)的方法是添加一个检查来比较以前的类别记录,以查看它们是否以您要处理的字符串开头
。代码中的$pos是一个参数,包含当前匹配的category元素的位置,$field-text是一个变量,包含您要输出的文本。
这是完整的 XSLT 样式表,它也应该为您提供所需的输出
Another way to do this without making use of extension function (but which will not necessarily be as efficient asusing Muenchian grouping) is to add a check to compare previous category records to see if they begin with the string you are about to about
In this bit of code $pos is a parameter containing the position of the current category element you are currently matching, and $field-text is a variable containing the text you are about to output.
Here is the complete XSLT stylesheet, which should also give you the output you desire
如果没有扩展函数,此样式表:
输出:
Without extension functions, this stylesheet:
Output: