如何在必要的地方将序列属性转换为单个元素?

时间:2009-08-27 07:37:44

标签: xslt xpath

我必须将属性设置为单个元素。请指导我。

这是我的输入和要求。

输入:

<book pagenum="01">
<title pagenum="01">Book title</title>
<chapter pagenum="02">
<chaptertitle pagenum="02">CHAPTER TITLE</chaptertitle>
<section pagenum="03">
<sectiontitle pagenum="03">SECTION TITLE</chaptertitle>
<subsection pagenum="04">
<para pagenum="04">body content</para>
<para pagenum="04">body content</para>
<para pagenum="04">body content</para>
<para pagenum="05">body content</para>
<para pagenum="05">body content</para>
<para pagenum="05">body content</para>
<para pagenum="06">body content</para>
<para pagenum="06">body content</para>
</subsection></section></chapter></book>

输出:

<book>
<?docpage num="01"?><pagenum id="p01">01</pagenum>
<booktitle>Book title</booktitle>
<chapter>
<?docpage num="02"?><pagenum id="p02">02</pagenum>
<chaptertitle>CHAPTER TITLE</chaptertitle>
<section>
<?docpage num="03"?><pagenum id="p03">03</pagenum>
<sectiontitle>SECTION TITLE</chaptertitle>
<subsection>
<?docpage num="04"?><pagenum id="p04">04</pagenum>
<para>body content</para>
<para>body content</para>
<para>body content</para>
<?docpage num="05"?><pagenum id="p05">05</pagenum>
<para>body content</para>
<para>body content</para>
<para>body content</para>
<?docpage num="06"?><pagenum id="p06">06</pagenum>
<para>body content</para>
<para>body content</para>
</subsection></section></chapter></book>

如何在XSLT脚本中转换它...?请指导我。

谢谢, 迈克尔

2 个答案:

答案 0 :(得分:2)

这些方面的东西:

<!-- Identity transform - copy all elements as is by default -->
<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

<!-- Match any element for which @pagenum is different from preceding one.
     Note that <para> is handled specially below. -->
<xsl:template match="*[@pagenum != preceding::*[1]/@pagenum]">
  <xsl:copy>
    <!-- Insert the PI and <pagenum> as first child -->
    <xsl:call-template name="insert-pagenum"/>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

<!-- Match <para> for which @pagenum is different from preceding one. -->
<xsl:template match="para[@pagenum != preceding::*[1]/@pagenum]">
  <!-- Insert the PI and <pagenum> before the opening tag of <para> -->
  <xsl:call-template name="insert-pagenum"/>
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

<xsl:template name="insert-pagenum">
  <xsl:processing-instruction name="docpage">
    <xsl:text>num=</xsl:text><xsl:value-of select="@pagenum"/>
  </xsl:processing-instruction>
  <pagenum id="p{@pagenum}">
    <xsl:value-of select="@pagenum"/>
  </pagenum>
</xsl:template>

答案 1 :(得分:2)

所以你只想为每个第一个写@pagenum?类似的东西:

<?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" indent="yes"/>
  <xsl:key name="pages" match="//@pagenum" use="." />

  <xsl:template match="@* | node()">
    <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
  </xsl:template>
  <xsl:template match="@pagenum">
    <xsl:if test="generate-id() = generate-id(key('pages', .))">
      <xsl:processing-instruction name="docpage">num=<xsl:value-of select="."/></xsl:processing-instruction>
      <pagenum id="p{.}"><xsl:value-of select="."/></pagenum>
    </xsl:if>
  </xsl:template>
  <xsl:template match="title">
    <booktitle><xsl:apply-templates select="@* | node()"/></booktitle>
  </xsl:template>
</xsl:stylesheet>