Xml 使用XSLT迭代属性值

Xml 使用XSLT迭代属性值,xml,xslt,xpath,Xml,Xslt,Xpath,我有一个XML结构,比如 <Object id="id0000" link="id0010 id0020"> <Data id="id1000"> <DataValue name="Obj0000"/> </Data> </Object> 我有几个“对象”节点,其中一些有一个链接,一些有两个或更多链接。链接(ID)之间用空格分隔。我已经使用了'tokenize()'-函数来获取各个链接ID <xs

我有一个XML结构,比如

<Object id="id0000" link="id0010 id0020">
    <Data id="id1000">
      <DataValue name="Obj0000"/>
    </Data>
</Object>

我有几个“对象”节点,其中一些有一个链接,一些有两个或更多链接。链接(ID)之间用空格分隔。我已经使用了'tokenize()'-函数来获取各个链接ID

<xsl:variable name="links">
    <xsl:value-of select="tokenize(@link, ' ')"/>
</xsl:variable>

每个链接都引用另一个包含一些数据的“对象”

现在我想使用链接(ID)的位置作为字符串,因此我的输出应该类似于

<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>

Obj0000
id0010
id0010
1.Obj0000的链接
id0020
id0020
2.Obj0000的链接
我发现很多页面都说,迭代和保存当前位置是无法用这种方式完成的,必须以某种方式解决。我找到了类似的东西

<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>


假设您有多个对象,我在源文件中添加了一个根元素:

<?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>

Obj0000
id0010
id0010
1.Obj0000的链接
id0020
id0020
2.Obj0000的链接

尽管这是所需的输出结构,但不确定这是否正确,我猜测LinkedObjects应该在每个对象中,但是这种更改很小…

正如我现在所做的(如上所述)使用“调用模板”而不是“应用模板”,我的上下文不会改变,因此现在我可以在调用模板中编写
。在调用的模板中,我现在可以编写
。该位置将始终获得当前链接,因为它在此模板中递增。我添加了一个答案,作为旁注,不要在变量中使用
,这将再次提供相同的字符串,可以使用
xsl:sequence
或使用变量的select属性。我当前在调用“LinkedObj”模板。在此模板中,我使用参数“position”(将递增)来获取标记化字符串的内容,如
$links[$position]
。因此,我可能没有理解全部要点:我存储在参数“link”中的标记化字符串基本上只是一个字符串(分成一系列子字符串).每次调用“LinkedObj”时,我都希望访问不同的子字符串“模板。我尝试使用你的想法,直到我意识到我必须传递每个属性和节点,我想稍后将其作为参数处理,因为模板是用字符串而不是节点调用的。我已经按照我的方式工作了,但是现在我想知道是否值得努力改变我的代码来使用你的想法。我认为这与“完成这样一项任务的常见方式”有关,我不知道常见方式。