我刚刚开始研究XSLT。我的输入和预期输出如下,XSLT也在下面给出。我现在面临两个问题
net.sf.saxon.trans.XPathException: Required item type of the context item for the attribute axis is node(); supplied value has item type xs:string
<students>
<field name="id">1,2,3</field>
<field name="name">a,b,c</field>
</students>
<students>
<student>
<id>1</id>
<name>a</name>
</student>
<student>
<id>2</id>
<name>b</name>
</student>
<student>
<id>3</id>
<name>c</name>
</student>
</students>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/" name="main">
<xsl:for-each select="students/field">
<xsl:for-each select="tokenize(.,',')">
<xsl:element name="{@name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:4)
我不确定为什么您展示的样式表使用XSLT 1.0,因为您使用XSLT 2.0标记了问题,而tokenize是2.0函数。
此外,您的预期输出包含我认为的拼写错误。也许这就是你的意思:
<student>
<id>1</id>
<name>a</name>
</student>
<student>
<id>2</id>
<name>b</name>
</student>
为什么会出现例外情况
在XSLT中,表达式在很大程度上依赖于上下文。如下所示的行:
<xsl:element name="{@name}">
取决于上下文,因为它检索当前模板匹配的name
属性值或xsl:for-each
中的当前项。
在您的情况下,上下文是这样的:
<xsl:for-each select="tokenize(.,',')">
因此,{@name}
的上下文是一个标记化的字符串 - 当然没有任何属性。
<强>样式表强>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/students">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="field[@name='id']">
<xsl:variable name="match" select="."/>
<xsl:for-each select="tokenize(.,',')">
<xsl:variable name="id-pos" select="position()"/>
<student>
<id>
<xsl:value-of select="."/>
</id>
<name>
<xsl:value-of select="tokenize($match/following-sibling::field[@name='name'],',')[position() = $id-pos]"/>
</name>
</student>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<强>输出强>
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student>
<id>1</id>
<name>a</name>
</student>
<student>
<id>2</id>
<name>b</name>
</student>
<student>
<id>3</id>
<name>c</name>
</student>
</students>
答案 1 :(得分:2)
假设您不知道field
元素的数量和名称,则以下内容更通用(并避免多次标记值):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="students">
<xsl:copy>
<xsl:variable name="fields">
<fields>
<xsl:variable name="fields" select="field"/>
<xsl:for-each select="field">
<xsl:variable name="field" select="."/>
<xsl:element name="{@name}s">
<xsl:for-each select="tokenize(., ',')">
<xsl:element name="{$field/@name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</fields>
</xsl:variable>
<xsl:for-each select="$fields/fields/*[1]/*">
<xsl:variable name="pos" select="position()"/>
<student>
<xsl:copy-of select="$fields/fields/*/*[$pos]"/>
</student>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>