使用XSLT转换扩展XML深度

时间:2014-01-28 23:55:10

标签: xslt xslt-2.0

我正在尝试转换一个具有根元素和一层子元素的xml。这些元素可以具有相同的属性名称。我正在寻找的是一种以相关属性正确嵌套的方式转换xml的方法。

xml是由HTML表单提交生成的(我可以控制表单字段名称)。

生成生成的XML:

Input.xml文件

<root>
<project_id>1</project_id>
<project_name>Project 1</project_name>
<project_id>2</project_id>
<project_name>Project 2</project_name>
<project_id>3</project_id>
<project_name>Project 3</project_name>
</root>

期望的输出

  <root>
    <project>
      <id>1</id>
      <name>Project 1</name>
    </project>

    <project>
      <id>2</id>
      <name>Project 2</name>
    </project>

    <project>
      <id>3</id>
      <name>Project 3</name>
    </project>
    <root>

我的尝试

注意:我将'r_'添加到重复的属性中。 <r_project_id> 2</r_project_id>

<xsl:template match="/">
    <root>
        <xsl:apply-templates/>
    </root>

</xsl:template>

<xsl:template match="node()|@*">
    <project>
        <xsl:apply-templates select="*[matches(name(), '^project_')]"/>
    </project>
    <project>
        <xsl:apply-templates select="*[matches(name(), '^r_project')]"/>
    </project>
</xsl:template>

<xsl:template match="*[matches(name(), '^r_project_')]">
    <xsl:apply-templates select="*[matches(name(), '^r_project_')]"/>
    <xsl:copy-of select="*"/>

</xsl:template>


<xsl:template match="*[matches(name(), '^project_')]">
    <xsl:element name="{replace(name(), '^project_', '')}">
        <xsl:copy-of select="*"/>
    </xsl:element>
</xsl:template>

<xsl:template match="*[matches(name(), '^r_project_')]">
    <xsl:element name="{replace(name(), '^r_project_', '')}">
        <xsl:copy-of select="*"/>
    </xsl:element>
</xsl:template>

的Output.xml

  <root>
      <project>
        <id></id>
        <name></name>
      </project>
      <project>
        <id></id>
        <name></name>
        <id></id>
        <name></name>
      </project>
    </root>

是否有一种更简单的方法来创建唯一的XML元素,而无需创建捕获所有可能重复元素的极其冗长的xslt转换?

2 个答案:

答案 0 :(得分:2)

来自michael.hor257k的解决方案看起来不错,但XSLT 2.0中的一个更惯用且更灵活的解决方案可能

<xsl:template match="/">
<root>
    <xsl:for-each-group select="root/*" group-starting-with="project_id">
        <project>
            <xsl:apply-templates select="current-group()" mode="rename"/>
        </project>
    </xsl:for-each>
</root>
</xsl:template>

<xsl:template match="*" mode="rename">
  <xsl:element name="{substring-after(name(), 'project_')}">
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

答案 1 :(得分:1)

我无法遵循XSLT的逻辑。有什么理由不能简单地说:

<xsl:template match="/">
<root>
    <xsl:for-each select="root/project_id">
        <project>
            <id><xsl:value-of select="."/></id>
            <name><xsl:value-of select="following-sibling::project_name"/></name>
        </project>
    </xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>