如何在XSLT 2.0中转换内部Node结构

时间:2018-01-23 08:40:51

标签: xml xslt xslt-2.0

我一直试图解决这个转型问题。

<ParentNode>
    <RequirementGroup>
        <ID>id1</ID>
        <Requirement>
            <ID>id2</ID>
            <Description>value1</Description>
        </Requirement>
        <RequirementGroup pi="attribute">
            <ID>id3</ID>
            <Requirement>
                <ID>id4</ID>
                <Description>value2</Description>
            </Requirement>
            <Requirement>
                <ID>id5</ID>
                <Description>value3</Description>
            </Requirement>
            <Requirement>
                <ID>id6</ID>
                <Description>value4</Description>
            </Requirement>
            <Requirement>
                <ID>id7</ID>
                <Description>value5</Description>
            </Requirement>
            <RequirementGroup>
                <ID>id8</ID>
                <Requirement>
                    <ID>id9</ID>
                    <Description>value6</Description>
                </Requirement>
                <RequirementGroup pi="attribute">
                    <ID>id10</ID>
                    <Requirement>
                        <ID>id11</ID>
                        <Description>value7</Description>
                    </Requirement>
                </RequirementGroup>
            </RequirementGroup>
        </RequirementGroup>
        <RequirementGroup>
            <ID>id12</ID>
            <Requirement>
                <ID>id13</ID>
                <Description>value8</Description>
            </Requirement>
            <RequirementGroup pi="attribute">
                <ID>id14</ID>
                <Requirement>
                    <ID>id15</ID>
                    <Description>value9</Description>
                </Requirement>
                <Requirement>
                    <ID>id16</ID>
                    <Description>value10</Description>
                </Requirement>
                <Requirement>
                    <ID>id17</ID>
                    <Description>value11</Description>
                </Requirement>
            </RequirementGroup>
        </RequirementGroup>
    </RequirementGroup>
</ParentNode>

关于这个XML结构,我想用其他节点名复制相同的结构,并将值复制到新的节点名中。

正如您所看到的,<RequirementGroup>节点具有另一个具有相同属性的相同节点。我可以到达第一个,但不是带有循环的内部。

<xsl:for-each select="RequirementGroup">
    <NewNode1>
        <xsl:if test="RequirementGroup">
            <xsl:call-template name="sometemplate" />
        </xsl:if>
        <xsl:if test="Requirement">
            <NewNode2>
                <xsl:call-template name="template" />
            </NewNode2>
        </xsl:if>
        <xsl:if test="RequirementGroup[@pi='attribute']">
            <xsl:for-each select="RequirementGroup[@pi='attribute']">
                <NewNode3>
                    <xsl:call-template name="anothertemplate" />
                    <xsl:if test="Requirement">
                        <xsl:for-each select="Requirement">
                            <NewNode2>
                                <xsl:call-template name="othertemplate" />
                            </NewNode2>
                        </xsl:for-each>
                    </xsl:if>
                </NewNode3>
            </xsl:for-each>
        </xsl:if>
    </NewNode1>
</xsl:for-each>

因此,使用此逻辑,我具有相同的结构,但只返回<RequirementGroup> pi属性中的一个。不是里面的其他人。对不起的解释感到抱歉,希望我设法告诉问题。

1 个答案:

答案 0 :(得分:0)

据我所知,你想将输入复制到输出, 仅更改元素名称,例如RequirementGroupNewNode1

因此,要执行上述更改(对于单个元素名称),您需要 以下模板:

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

对于每个其他元素,要更改哪个名称,您需要类似 模板,替换match条件和创建元素的名称。

另一个解决方案是创建一个&#34;复合材料&#34;一些元素名称的模板, 例如要将名称source_1source_2source_3更改为 target_1target_2target_3,创建如下内容:

<xsl:template match="source_1 | source_2 | source_3">
  <xsl:variable name="tagName" select="
    if (name() = 'source_1') then 'target_1'
    else if (name() = 'source_2') then 'target_2'
    else 'target_3'"/>
  <xsl:element name="{$tagName}">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

当然,在这两种情况下,您的脚本还必须包含身份模板

修改

又一个解决方案 - 一个&#34;通用&#34;模板(如下),包括:

  • 源名称和目标名称列表(长度相等)。
  • ind变量 - 源列表中当前元素名称的位置 (未找到 - 空)。
  • tagName变量 - 来自目标列表的目标元素名称或原始名称 (如果没有找到)。

其余部分与之前的解决方案相同。

<xsl:template match="*">
  <xsl:variable name="srcNames" select="('source_1','source_2','source_3')"/>
  <xsl:variable name="trgNames" select="('target_1','target_2','target_3')"/>
  <xsl:variable name="ind" select="index-of($srcNames, name())[1]"/>
  <xsl:variable name="tagName" select="
    if ($ind) then $trgNames[$ind] else name()"/>
  <xsl:element name="{$tagName}">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>