使用xslt将行转换为嵌套元素

时间:2013-12-13 23:28:51

标签: xslt

输入:

<data>
  <line>1grandparent-fname</line>
  <line>2parentfname</line>
  <line>3child1name</line>
  <line>4child2name</line>
  <line>3child1name</line>
  <line>4child2name</line>
  <line>5parent-lname</line>
  <line>6grandparent-lname</line>
</data>

预期产出:

<data>
  <grandparent fname="Grandparent-fname" lname="grandparent-lname">
    <parent fname="parentfname" lname="parent-lname">
      <child1>child1name</child1>
      <child2>child2name</child2>
      <child1>child1name</child1>
      <child2>child2name</child2>
    </parent>
  </grandparent>
</data>

有关如何使用xslt完成的任何想法?尝试了各种选择,但无法弄清楚。

第一个字母决定层次结构,1个祖父母fname,2个父fname,3个child1名称等等。父母和孩子重复,孩子1和2将是连续的,

1 个答案:

答案 0 :(得分:0)

这是一种可能的方法。它可能不是一个优雅的,但输入也不是。假设可能有多个祖父母和任何数字(包括奇数)的孩子。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/data">
<xsl:copy>
    <xsl:apply-templates select="line[starts-with(., '1')]">
        <xsl:with-param name="level" select="'grandparent'"/>
    </xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="line">
    <xsl:param name="level"/>
    <xsl:choose>
        <xsl:when test="$level='grandparent'">
            <xsl:variable name="end" select="following-sibling::line[starts-with(., '6')][1]" />
            <xsl:variable name="limit" select="count($end/preceding-sibling::line)" />
            <grandparent>
                <xsl:attribute name="fname">
                    <xsl:value-of select="substring(., 2)"/>
                </xsl:attribute>
                <xsl:attribute name="lname">
                    <xsl:value-of select="substring($end, 2)"/>
                </xsl:attribute>
                <xsl:apply-templates select="following-sibling::line[count(preceding-sibling::line) &lt; $limit][starts-with(., '2')]">
                    <xsl:with-param name="level" select="'parent'"/>
                </xsl:apply-templates>
            </grandparent>
        </xsl:when>

        <xsl:when test="$level='parent'">
            <xsl:variable name="end" select="following-sibling::line[starts-with(., '5')][1]" />
            <xsl:variable name="limit" select="count($end/preceding-sibling::line)" />
            <parent>
                <xsl:attribute name="fname">
                    <xsl:value-of select="substring(., 2)"/>
                </xsl:attribute>
                <xsl:attribute name="lname">
                    <xsl:value-of select="substring($end, 2)"/>
                </xsl:attribute>
                <xsl:apply-templates select="following-sibling::line[count(preceding-sibling::line) &lt; $limit][starts-with(., '3') or starts-with(., '4')]">
                    <xsl:with-param name="level" select="'child'"/>
                </xsl:apply-templates>
            </parent>
        </xsl:when>

        <xsl:when test="$level='child'">
            <child>
                <xsl:value-of select="substring(., 2)"/>    
            </child>
        </xsl:when>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>