我有一个以下XML文件:
<guests>
<guest roomnumber="111" email="john.perry@abc.com"/>
<guest roomnumber="112" email="JohnMarconi@lema.fr"/>
<guest roomnumber="114" email="John_kim@kema.nl"/>
<guest roomnumber="127" email="jim.taylor@sat.com"/>
<guest roomnumber="133" email="Jane.Doe@abc.com"/>
<guest roomnumber="135" email="janesullivan@ati.org"/>
<guest roomnumber="136" email="Albert.Jones@lec.org"/>
</guests>
并希望使用以'john'或'jane'开头的@email消除元素,执行不区分大小写的名称搜索。
生成的XML文件应如下所示:
<guests>
<guest roomnumber="127" email="jim.taylor@sat.com"/>
<guest roomnumber="136" email="Albert.Jones@lec.org"/>
</guests>
在转换中我想使用参数“Name”,例如
<xsl:param name="Name">
<x>john</x>
<x>jane</x>
</xsl:param>
或
<xsl:param name="Name" select="'john,jane'" />
如何使用XSLT 1.0实现这样的转换?唉,在我的情况下,不支持XSLT 2.0和document()函数。
TIA,Leo
答案 0 :(得分:2)
假设您将$name
参数作为实际XML文档传递(即,您没有在XSLT文档中定义它,因为这会产生{{3} },没有扩展功能就不容易使用):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:template match="*|@*">
<xsl:if test="
not(self::guest)
or
not($Name/x[starts-with(translate(current()/@email, $upper, $lower), .)])
">
<xsl:copy>
<xsl:apply-templates select="*|@*" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
如果您将$name
作为逗号分隔的字符串列表传递,那么事情会变得更复杂,所以我建议您先尝试传递XML文档。
编辑:以下是使用名称的内联定义和node-set()
的相同内容的版本:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl"
>
<xsl:output indent="yes" />
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:param name="Name">
<x>john</x>
<x>jane</x>
</xsl:param>
<xsl:variable name="Excluded" select="exsl:node-set($Name)/x" />
<xsl:template match="*|@*">
<xsl:if test="
not(self::guest)
or
not($Excluded[starts-with(translate(current()/@email, $upper, $lower), .)])
">
<xsl:copy>
<xsl:apply-templates select="*|@*" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
你可以尝试这些方法:
修改强>
正如Tomalak指出的那样,您需要使用非标准RTF
函数转换xxx:node-set()
(结果树片段)!
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext msxsl">
<xsl:variable name="lower">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="upper">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:template match="/guests">
<guests>
<xsl:call-template name="foo">
<xsl:with-param name="guests" select="guest"/>
<xsl:with-param name="terms">
<x>John</x>
<x>jane</x>
</xsl:with-param>
</xsl:call-template>
</guests>
</xsl:template>
<xsl:template name="foo">
<xsl:param name="guests"/>
<xsl:param name="terms"/>
<xsl:for-each select="$guests">
<xsl:call-template name="bar">
<xsl:with-param name="guest" select="."/>
<!-- HERE ARE THE EDITED LINES -->
<xsl:with-param name="prefix" select="ext:node-set($terms)/*"/>
<xsl:with-param name="runs" select="count(ext:node-set($terms)/*)"/>
<!-- HERE ARE THE EDITED LINES -->
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="bar">
<xsl:param name="runs" select="0"/>
<xsl:param name="guest"/>
<xsl:param name="prefix"/>
<xsl:if test="not(starts-with(translate($guest/@email, $upper, $lower), translate($prefix, $upper, $lower)))">
<xsl:choose>
<xsl:when test="$runs = 1">
<xsl:copy-of select="$guest"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="bar">
<xsl:with-param name="guest" select="$guest"/>
<xsl:with-param name="prefix" select="$prefix[not(position()=1)]"/>
<xsl:with-param name="runs" select="$runs - 1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>