XSLT副本&设置属性值

时间:2014-04-17 21:21:23

标签: xml xslt

以下是我的首发XML:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:something-well-formed"> 
  <child1 attr1="a" attr2="b"> 
     <child1 attr1="c" attr2="b"/>
  </child1>
  <child3/>
  <child1 attr1="d" attr2="b"> 
     <child2 attr1="e" attr2="b"/> 
  </child1>
</root>

在对上面的内容进行转换之后,我得到了一个中间结果xml,在这种情况下剥离了所有属性,从child1节点开始:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:something-well-formed"> 
   <child1> 
      <child1/>
   </child1>
   <child3/>
   <child1> 
      <child2 attr1="e" attr2="b"/> 
   </child1>
</root>

我想要做的是对上面生成的中间结果进行转换,以创建一个类似于下面示例的xml doc,在这种情况下,我可以指定第n个实例,在本例中, child1并相应地设置它的属性:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:something-well-formed"> 
   <child1  attr1="something", attr2="something else"> 
      <child1/>
   </child1>
   <child3/>
   <child1> 
      <child2 attr1="e" attr2="b"/> 
   </child1>
</root>

这是我尝试使用的xslt示例:

<xsl:param name="element" />
    <xsl:param name="attributes" />
    <xsl:param name="nodeNumber"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[name(.)=$element]">
        <xsl:copy>
            <xsl:apply-templates select="@*" />

            <!-- Splits into separate key/value pairs elements -->
            <xsl:variable name="attributesSeq" select="tokenize($attributes, ';')" />
            <xsl:for-each select="$attributesSeq">
                <xsl:variable name="attributesSeq" select="tokenize(., ',')" />

                <xsl:variable name="key"
                    select="replace($attributesSeq[1], '&quot;', '')" />
                <xsl:variable name="value"
                    select="replace($attributesSeq[2], '&quot;', '')" />

                <xsl:attribute name="{$key}">
                    <xsl:value-of select="$value" />
                </xsl:attribute>
            </xsl:for-each>

            <xsl:apply-templates select="node()" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

问题是上面的xslt复制&#34;属性&#34;参数到child1的每个实例,当我的目标是复制&#34;属性&#34;的内容时参数到child1的第n个实例。

其他问题:我希望参数化节点名称是我选择传入的任何节点名称的第n个实例。上面的示例使用child1,但它应该适用于任何节点名称(即child3, child37等。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

嗯。如果你限制你的孩子&#34;要成为根节点的第N个孩子,其名称由element给出,您可以使用您的方法,但您必须更换

<xsl:template match="*[name() = $element]">

通过

<xsl:template match="*[name() = $element][$nodeNumber]">

这对我有用(虽然xsltproc不接受语法,但我不得不使用Saxon)。但是,如果您希望定位名称由element提供的孩子的第N个后代实例,则它将无效。这将更棘手。我还没有找到答案。

答案 1 :(得分:1)

假设您收到此<xsl:param>中的号码:

<xsl:param name="nodeNumber" select='2'/>

您可以在模板中添加谓词,并将变量作为参数传递:

<xsl:template match="*[name(.)=$element][$nodeNumber]">
   ....
</xsl:template>

这将根据元素在调用它的上下文中的位置来限制元素。

您还有一个元素名称的参数。如果您使用:

<xsl:param name="element" select="'child1'" />

它会在child1上添加属性。如果您将其替换为'child3''child2',则会相应地替换它们。 (显然,child3child2在您的示例中$nodeNumber必须为1,因为每个只有一个。)