XSLT需要格式化XML文件中的目录

时间:2014-08-22 15:27:20

标签: xml xslt

我是样式表的新手,需要一个XSLT来格式化XML文件中的目录。

我的输入XML如下所示:

<tocheader>CONTENTS</tocheader>
<toccrossheading>Section 1</toccrossheading>
<tocsectionnumber>1Paragraph 1</tocsectionnumber>
<toccrossheading>Section 2</toccrossheading>
<tocsectionnumber>2Paragraph 2</tocsectionnumber>
<toccrossheading>Section 3</toccrossheading>
<tocsectionnumber>3Paragraph 3</tocsectionnumber>
<tocsectionnumber>4Paragraph 4</tocsectionnumber>
<toccrossheading>Section 4</toccrossheading>
<tocsectionnumber>5Paragraph 5</tocsectionnumber>
<tocsectionnumber>6Paragraph 6</tocsectionnumber>
<toccrossheading>Section 5</toccrossheading>
<tocsectionnumber>7Paragraph 7</tocsectionnumber>
<toccrossheading>Agricultural enforcement officers</toccrossheading>
<tocsectionnumber>8Paragraph 8</tocsectionnumber>
<tocsectionnumber>9Paragraph 9</tocsectionnumber>
<toccrossheading>Section 6</toccrossheading>
<tocsectionnumber>10Paragraph 10</tocsectionnumber>
<tocsectionnumber>11Paragraph 11</tocsectionnumber>
<tocsectionnumber>12Paragraph 12</tocsectionnumber>
<tocsectionnumber>13Paragraph 13</tocsectionnumber>
<tocsectionnumber>14Paragraph 14</tocsectionnumber>
<toccrossheading></toccrossheading>

我希望输出XML看起来像这样:

<ToC>
<TocTitle>CONTENTS</TocTitle>
<ToCsection>
<ToCsectionTitle>Section 1</ToCsectionTitle>
<TocItem>
<TocItemNumber>1</TocItemNumber>
<TocItemTitle>Paragraph 1</TocItemTitle>
</TocItem>
</ToCsection>
<ToCsection>
<ToCsectionTitle>Section 2</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>2</TocItemNumber>
<TocItemTitle>Paragraph 2</TocItemTitle>
</TocItem>
</ToCsection>
<ToCsection>
<ToCsectionTitle>Section 3</ToCsectionTitle>
<TocItem>
<TocItemNumber>3</TocItemNumber>
<TocItemTitle>Paragraph 3</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>4</TocItemNumber>
<TocItemTitle>Paragraph 4</TocItemTitle>
</TocItem>
</ToCsection>
<ToCsection>
<ToCsectionTitle>Section 4</ToCsectionTitle>
<TocItem>
<TocItemNumber>5</TocItemNumber>
<TocItemTitle>Paragraph 5</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>6</TocItemNumber>
<TocItemTitle>Paragraph 6</TocItemTitle>
</TocItem>
</ToCsection>
<ToCsection>
<ToCsectionTitle>Section 5</ToCsectionTitle>
<TocItem>
<TocItemNumber>7</TocItemNumber>
<TocItemTitle>Paragraph 7</TocItemTitle>
</TocItem>
</ToCsection>
<ToCsection>
<ToCsectionTitle>Agricultural enforcement officers</ToCsectionTitle>
<TocItem>
<TocItemNumber>8</TocItemNumber>
<TocItemTitle>Paragraph 8</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>9</TocItemNumber>
<TocItemTitle>Paragraph 9</TocItemTitle>
</TocItem>
</ToCsection>
<ToCsection>
<ToCsectionTitle>Section 6</ToCsectionTitle>
<TocItem>
<TocItemNumber>10</TocItemNumber>
<TocItemTitle>Paragraph 10</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>11</TocItemNumber>
<TocItemTitle>Paragraph 11</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>12</TocItemNumber>
<TocItemTitle>Paragraph 12</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>13</TocItemNumber>
<TocItemTitle>Paragraph 13</TocItemTitle>
</TocItem>
<TocItem>
<TocItemNumber>14</TocItemNumber>
<TocItemTitle>Paragraph 14</TocItemTitle>
</TocItem>
</ToCsection>
</ToC>

我一直在玩下面的XSLT代码,但没有取得任何成功:

<xsl:template match="ToC">
<ToC>
<TocTitle><xsl:apply-templates select="*"/></TocTitle>
</ToC>
</xsl:template>

非常感谢任何帮助。 感谢。

2 个答案:

答案 0 :(得分:1)

获取您要求的输出有两个主要部分:

  1. 基于toccrossheading
  2. 进行分组
  3. 用于分隔tocsectionnumber
  4. 的字符串操作

    在XSLT 2.0中,分组和字符串操作都要容易得多。

    1.0中的分组通常使用xsl:key使用substring()完成。在我的例子中,我没有使用muenchian分组。相反,我比较了生成的id。我认为这会更容易理解,但我可能是错的。此外,我不太擅长muenchian分组,因为我主要使用XSLT 2.0,它有不同/更容易(我认为)的分组方式。你仍然可以在2.0中使用muenchian分组。

    1.0中的基本字符串操作通常使用substring-before()substring-after()tocsectionnumber完成。如果它很复杂,可以使用递归模板。我的下面的示例非常脆弱,因为Paragraph必须始终包含文本<toc> <tocheader>CONTENTS</tocheader> <toccrossheading>Section 1</toccrossheading> <tocsectionnumber>1Paragraph 1</tocsectionnumber> <toccrossheading>Section 2</toccrossheading> <tocsectionnumber>2Paragraph 2</tocsectionnumber> <toccrossheading>Section 3</toccrossheading> <tocsectionnumber>3Paragraph 3</tocsectionnumber> <tocsectionnumber>4Paragraph 4</tocsectionnumber> <toccrossheading>Section 4</toccrossheading> <tocsectionnumber>5Paragraph 5</tocsectionnumber> <tocsectionnumber>6Paragraph 6</tocsectionnumber> <toccrossheading>Section 5</toccrossheading> <tocsectionnumber>7Paragraph 7</tocsectionnumber> <toccrossheading>Agricultural enforcement officers</toccrossheading> <tocsectionnumber>8Paragraph 8</tocsectionnumber> <tocsectionnumber>9Paragraph 9</tocsectionnumber> <toccrossheading>Section 6</toccrossheading> <tocsectionnumber>10Paragraph 10</tocsectionnumber> <tocsectionnumber>11Paragraph 11</tocsectionnumber> <tocsectionnumber>12Paragraph 12</tocsectionnumber> <tocsectionnumber>13Paragraph 13</tocsectionnumber> <tocsectionnumber>14Paragraph 14</tocsectionnumber> <toccrossheading></toccrossheading> </toc>

    无论如何,这里有一个你可以编写这个变换的方法的例子......

    XML输入(添加根元素以使格式正确)

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="/*">
            <ToC>
                <TocTitle><xsl:apply-templates select="tocheader"/></TocTitle>
                <xsl:apply-templates select="toccrossheading[string()]">
                    <!--I use [string()] here to skip the empty toccrossheading
                    in the sample input.-->
                </xsl:apply-templates>
            </ToC>
        </xsl:template>
    
        <xsl:template match="toccrossheading">
            <ToCsection>
                <ToCsectionTitle>
                    <xsl:value-of select="."/>
                </ToCsectionTitle>
                <xsl:apply-templates select="following-sibling::tocsectionnumber[generate-id(current())=generate-id(preceding-sibling::toccrossheading[1])]">
                    <!--This is the only slightly tricky part of
                    the stylesheet. This is where I'm comparing
                    generated id's of the current toccrossheading
                    and the first preceding sibling toccrossheading 
                    of the following sibling tocsectionnumber's.-->
                </xsl:apply-templates>
            </ToCsection>
        </xsl:template>
    
        <xsl:template match="tocsectionnumber">
            <TocItem>
                <TocItemNumber>
                    <xsl:value-of select="substring-before(.,'Paragraph')"/>
                </TocItemNumber>
                <TocItemTitle>
                    <xsl:text>Paragraph</xsl:text>
                    <xsl:value-of select="substring-after(.,'Paragraph')"/>
                </TocItemTitle>
            </TocItem>
        </xsl:template>
    
    </xsl:stylesheet>
    

    XSLT 1.0

    <ToC>
       <TocTitle>CONTENTS</TocTitle>
       <ToCsection>
          <ToCsectionTitle>Section 1</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>1</TocItemNumber>
             <TocItemTitle>Paragraph 1</TocItemTitle>
          </TocItem>
       </ToCsection>
       <ToCsection>
          <ToCsectionTitle>Section 2</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>2</TocItemNumber>
             <TocItemTitle>Paragraph 2</TocItemTitle>
          </TocItem>
       </ToCsection>
       <ToCsection>
          <ToCsectionTitle>Section 3</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>3</TocItemNumber>
             <TocItemTitle>Paragraph 3</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>4</TocItemNumber>
             <TocItemTitle>Paragraph 4</TocItemTitle>
          </TocItem>
       </ToCsection>
       <ToCsection>
          <ToCsectionTitle>Section 4</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>5</TocItemNumber>
             <TocItemTitle>Paragraph 5</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>6</TocItemNumber>
             <TocItemTitle>Paragraph 6</TocItemTitle>
          </TocItem>
       </ToCsection>
       <ToCsection>
          <ToCsectionTitle>Section 5</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>7</TocItemNumber>
             <TocItemTitle>Paragraph 7</TocItemTitle>
          </TocItem>
       </ToCsection>
       <ToCsection>
          <ToCsectionTitle>Agricultural enforcement officers</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>8</TocItemNumber>
             <TocItemTitle>Paragraph 8</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>9</TocItemNumber>
             <TocItemTitle>Paragraph 9</TocItemTitle>
          </TocItem>
       </ToCsection>
       <ToCsection>
          <ToCsectionTitle>Section 6</ToCsectionTitle>
          <TocItem>
             <TocItemNumber>10</TocItemNumber>
             <TocItemTitle>Paragraph 10</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>11</TocItemNumber>
             <TocItemTitle>Paragraph 11</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>12</TocItemNumber>
             <TocItemTitle>Paragraph 12</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>13</TocItemNumber>
             <TocItemTitle>Paragraph 13</TocItemTitle>
          </TocItem>
          <TocItem>
             <TocItemNumber>14</TocItemNumber>
             <TocItemTitle>Paragraph 14</TocItemTitle>
          </TocItem>
       </ToCsection>
    </ToC>
    

    XML输出

    {{1}}

答案 1 :(得分:0)

您的输入需要根元素,例如

<root>
<tocheader>CONTENTS</tocheader>
<toccrossheading>Section 1</toccrossheading>
<tocsectionnumber>1Paragraph 1</tocsectionnumber>
<toccrossheading>Section 2</toccrossheading>
<tocsectionnumber>2Paragraph 2</tocsectionnumber>
<toccrossheading>Section 3</toccrossheading>
<tocsectionnumber>3Paragraph 3</tocsectionnumber>
<tocsectionnumber>4Paragraph 4</tocsectionnumber>
<toccrossheading>Section 4</toccrossheading>
<tocsectionnumber>5Paragraph 5</tocsectionnumber>
<tocsectionnumber>6Paragraph 6</tocsectionnumber>
<toccrossheading>Section 5</toccrossheading>
<tocsectionnumber>7Paragraph 7</tocsectionnumber>
<toccrossheading>Agricultural enforcement officers</toccrossheading>
<tocsectionnumber>8Paragraph 8</tocsectionnumber>
<tocsectionnumber>9Paragraph 9</tocsectionnumber>
<toccrossheading>Section 6</toccrossheading>
<tocsectionnumber>10Paragraph 10</tocsectionnumber>
<tocsectionnumber>11Paragraph 11</tocsectionnumber>
<tocsectionnumber>12Paragraph 12</tocsectionnumber>
<tocsectionnumber>13Paragraph 13</tocsectionnumber>
<tocsectionnumber>14Paragraph 14</tocsectionnumber>
<toccrossheading></toccrossheading>
</root>

然后你可以使用像这样的

模板进行击中
<xsl:template match="/root">
    <ToC>
        <TocTitle><xsl:value-of select="tocheader"/></TocTitle>
    </ToC>
</xsl:template>

匹配/将表示根范围,因此您可以针对此范围内的元素选择或匹配模板或遍历....无论如何!