我有像
这样的XML结构<Object id="id0000" link="id0010 id0020">
<Data id="id1000">
<DataValue name="Obj0000"/>
</Data>
</Object>
我有几个'Object'节点,其中一些有一个链接,其中一些有两个或多个链接。链接(ID)由空格分隔。我已经使用'tokenize()' - 函数来获取单个链接ID
<xsl:variable name="links">
<xsl:value-of select="tokenize(@link, ' ')"/>
</xsl:variable>
每个链接指的是带有一些数据的另一个“对象”。
现在我想使用链接(ids)的位置作为字符串,所以我的输出应该看起来像
<Object>
<hasName>Obj0000</hasName>
<hasStartLink>id0010</hasStartLink>
</Object>
<LinkedObject>
<hasID>id0010</hasID>
<hasDescription>1. link of Obj0000</hasDescription>
<hasNextLink>id0020</hasNextLink>
</LinkedObject>
<LinkedObject>
<hasID>id0020</hasID>
<hasDescription>2. link of Obj0000</hasDescription>
</LinkedObject>
我发现许多页面都说,迭代并保存当前位置是不能以这种方式完成的事情,必须以某种方式解决。我找到了像
这样的东西<!-- inside another template -->
<xsl:call-template name="LinkedObj">
<xsl:with-param name="count" select="1"/>
</xsl:call-template>
<!-- end of another template -->
<xsl:template name="LinkedObj">
<xsl:param name="count"/>
<!-- do some stuff here -->
<!-- use '$count' as position -->
<xsl:call-template name="LinkedObj>
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:template>
但是现在我不知道我可以使用这样的模板。我宁愿不再在模板本身中调用模板,而是在“另一个模板”中调用模板。但在这个(“另一个”)模板里面,我没有当前的count变量,对吗? 在'LinkedObj'模板中,我已经在另一个上下文中,所以我不知道有多少次我应该调用另一个模板(我没有'链接')。 目前我正在使用两个参数,所以我正在检查我的位置是否小于属性数(链接):
<xsl:template match="Object">
<xsl:element name="Object>
<xsl:element name="hasName">
<xsl:value-of select="Data/DataValue/@name"/>
</xsl:element>
<xsl:element name="hasStartLink">
<!-- here I'm also not sure how to get only the first separated id -->
</xsl:element>
</xsl:element>
<xsl:call-template name="LinkedObj">
<xsl:with-param name="position" select="1"/>
<xsl:with-param name="count" select="count(tokenize(@link, ' '))"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="LinkedObj">
<xsl:param name="position"/>
<xsl:param name="count"/>
<!-- do some stuff here -->
<!-- use '$position' as position -->
<xsl:if test="$position < $count">
<xsl:call-template name="LinkedObj>
<xsl:with-param name="position" select="$position + 1"/>
<xsl:with-param name="count" select="$count"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
对此有何建议?
下一步不仅要获取位置并将其用于文本输出,还要使用链接的ID来调用或应用新模板。正如我在最后一个代码块中所评论的那样,我不知道如何将标记化字符串的元素用作节点。我用for-each元素尝试了它,但是我没有这样做,因为有一些上下文错误(我必须重现它并在这里发布)。
编辑: 我发现了一种让它工作的方法,这与Tobias的想法不同,所以我在这里发布基本代码:
<xsl:template match="Object">
<xsl:element name="Object>
<xsl:element name="hasName">
<xsl:value-of select="Data/DataValue/@name"/>
</xsl:element>
<xsl:element name="hasStartLink">
<!-- here I'm also not sure how to get only the first separated id -->
</xsl:element>
</xsl:element>
<xsl:call-template name="LinkedObj">
<xsl:with-param name="position" select="1"/>
<xsl:with-param name="count" select="count(tokenize(@link, ' '))"/>
<xsl:with-param name="links" select="tokenize(@link, ' ')"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="LinkedObj">
<xsl:param name="position"/>
<xsl:param name="count"/>
<xsl:param name="links"/>
<xsl:element name="hasID">
<xsl:value-of select="$links[$position]"/>
</xsl:element>
<xsl:element name="hasDescription">
<xsl:value-of select="concat($position, '. link of ', Data/DataValue/@name)"/>
</xsl:element>
<xsl:if test="$position < $count">
<xsl:element name="hasNextLink">
<xsl:value-of select="$links[$position + 1]"/>
</xsl:element>
<xsl:call-template name="LinkedObj>
<xsl:with-param name="position" select="$position + 1"/>
<xsl:with-param name="count" select="$count"/>
<xsl:with-param name="links" select="$links"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
在这种情况下,可以在“LinkedObj”模板中获取“Object”的值,因为模板是使用节点调用的(“Object”,因为上下文不会更改)。
答案 0 :(得分:0)
假设您有多个对象,我在源文件中添加了一个根元素:
<?xml version="1.0" encoding="UTF-8"?>
<Objects>
<Object id="id0000" link="id0010 id0020">
<Data id="id1000">
<DataValue name="Obj0000"/>
</Data>
</Object>
</Objects>
您不必使用LinkedObj模板的递归调用,您可以遍历链接并调用循环:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="Objects">
<Objects>
<xsl:apply-templates select="Object"/>
</Objects>
</xsl:template>
<xsl:template match="Object">
<xsl:variable name="name" select="Data/DataValue/@name"/>
<xsl:variable name="links" select="tokenize(@link, ' ')"/>
<xsl:element name="Object">
<xsl:element name="hasName">
<xsl:value-of select="$name"/>
</xsl:element>
<xsl:element name="hasStartLink">
<xsl:value-of select="$links[1]"/>
</xsl:element>
</xsl:element>
<xsl:for-each select="$links">
<xsl:variable name="position" select="position()"/>
<xsl:call-template name="LinkedObj">
<xsl:with-param name="position" select="$position"/>
<xsl:with-param name="id" select="."/>
<xsl:with-param name="nextLink" select="$links[$position + 1]"/>
<xsl:with-param name="objectName" select="$name"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="LinkedObj">
<xsl:param name="position"/>
<xsl:param name="id"/>
<xsl:param name="nextLink"/>
<xsl:param name="objectName"/>
<LinkedObject>
<hasID>
<xsl:value-of select="$id"/>
</hasID>
<hasDescription>
<xsl:value-of select="position()"/>
<xsl:text>. link of </xsl:text>
<xsl:value-of select="$objectName"/>
</hasDescription>
<xsl:if test="$nextLink!=''">
<hasNextLink>
<xsl:value-of select="$nextLink"/>
</hasNextLink>
</xsl:if>
</LinkedObject>
</xsl:template>
</xsl:stylesheet>
结果:
<?xml version="1.0" encoding="UTF-8"?>
<Objects>
<Object>
<hasName>Obj0000</hasName>
<hasStartLink>id0010</hasStartLink>
</Object>
<LinkedObject>
<hasID>id0010</hasID>
<hasDescription>1. link of Obj0000</hasDescription>
<hasNextLink>id0020</hasNextLink>
</LinkedObject>
<LinkedObject>
<hasID>id0020</hasID>
<hasDescription>2. link of Obj0000</hasDescription>
</LinkedObject>
</Objects>
虽然这是必需的输出结构,但不确定这是否正确,我猜测LinkedObjects应该在每个Object中,但是这种改变是微不足道的......