在XSLT中,如何插入适用于不同模板的匹配标记

时间:2011-05-20 14:57:56

标签: xml xslt

我是XSLT的新手,但我还没有找到解决问题的方法。我有一个看起来像的xml文件(我不能改变这个xml看起来的方式,意识到它有点奇怪):

<account>
    <name>accountA</name>
</account>
<period>
    <type>priormonth</type>
</period>
<period>
    <type>currentmonth</type>
</period>
<account>
    <name>accountB</name>
</account>
<period>
    <type>priormonth</type>
</period>
<period>
    <type>currentmonth</type>
</period>

xml文件可以包含变量帐号/期间/期间数据集,但它们始终按此顺序排列。

我有一个xsl文件,看起来像:

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

<xsl:template match="account">
    <name> <xsl:value-of select="name"/> </name>
</xsl:template>

<xsl:template match="period">
    <type> <xsl:value-of select="type"/> </type>
</xsl:template>

以上工作很有效,因为它处理多个帐户/期间/期间的事件,我的输出如下:

<name>accountA</name>
<type>priormonth</type>
<type>currentmonth</type>
<name>accountB</name>
<type>priormonth</type>
<type>currentmonth</type>

但是,我想要插入一些额外的标签,以便输出看起来像:

<account>
    <name>accountA</name>
    <period>
        <type>priormonth</type>
        <type>currentmonth</type>
    </period>
</account>
<account>
    <name>accountB</name>
    <period>
        <type>priormonth</type>
        <type>currentmonth</type>
    </period>
</account>

有没有办法做到这一点?如果我的术语不太正确,请道歉。 谢谢

2 个答案:

答案 0 :(得分:2)

试试这个:

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

  <xsl:template match="account">
    <xsl:copy>
      <xsl:apply-templates />
      <period>
        <xsl:apply-templates select="following-sibling::period[generate-id(preceding-sibling::account[1]) = generate-id(current())]/*" />
      </period>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="period" />

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

select语句有点复杂,但基本上它选择了每个period元素之后的所有account兄弟节点,其中前面的第一个account元素是当前元素

答案 1 :(得分:1)

以下XSLT假定xml源与您的问题中完全一致(除了缺少的根目录,这使得源文档不能很好地形成)。在这种情况下,您不需要身份转换。此外,如果您的account确实只需要前两个period,那么您可以使用更简单的XPath。


Saxon-HE 9.2.1.1J 下测试

XSLT 1.0

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

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

    <xsl:template match="account">
        <xsl:copy>
            <xsl:copy-of select="name" />
            <period>
                <xsl:copy-of select="following-sibling::period[position()&lt;=2]/type" />
            </period>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="period" />

</xsl:stylesheet>

应用于此输入:

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
    <account>
        <name>accountA</name>
    </account>
    <period>
        <type>march</type>
    </period>
    <period>
        <type>currentmonth</type>
    </period>
    <account>
        <name>accountB</name>
    </account>
    <period>
        <type>priormonth</type>
    </period>
    <period>
        <type>currentmonth</type>
    </period>
</root>

给出:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <account>
      <name>accountA</name>
      <period>
         <type>march</type>
         <type>currentmonth</type>
      </period>
   </account>
   <account>
      <name>accountB</name>
      <period>
         <type>priormonth</type>
         <type>currentmonth</type>
      </period>
   </account>
</root>