使用XSLT订购可选元素

时间:2018-10-17 08:23:59

标签: xslt

我有一些XML表示不同的项目,每个项目具有三个字段(field1,field2,field3),还可以选择两个额外的字段(field4,field5),如下所示:

<items>
    <data type="basic">
        <field1>A1</field1>
        <field2>A2</field2>
        <field3>A3</field3>
    </data>
    <data type="basic">
        <field1>B1</field1>
        <field2>B2</field2>
        <field3>B3</field3>
    </data>
    <data type="basic">
        <field1>C1</field1>
        <field2>C2</field2>
        <field3>C3</field3>
    </data>
    <data type="extra">
        <field4>C4</field4>
        <field5>C5</field5>
    </data>
    <data type="basic">
        <field1>D1</field1>
        <field2>D2</field2>
        <field3>D3</field3>
    </data>
    <data type="basic">
        <field1>E1</field1>
        <field2>E2</field2>
        <field3>E3</field3>
    </data>
    <data type="extra">
        <field4>E4</field4>
        <field5>E5</field5>
    </data>
</items>

我想以一种更加有序的方式对它们进行分组,如下所示:

<items>
    <item>
        <field1>A1</field1>
        <field2>A2</field2>
        <field3>A3</field3>
    </item>
    <item>
        <field1>B1</field1>
        <field2>B2</field2>
        <field3>B3</field3>
    </item>
    <item>
        <field1>C1</field1>
        <field2>C2</field2>
        <field3>C3</field3>
        <field4>C4</field4>
        <field5>C5</field5>
    </item>
    <item>
        <field1>D1</field1>
        <field2>D2</field2>
        <field3>D3</field3>
    </item>
    <item>
        <field1>E1</field1>
        <field2>E2</field2>
        <field3>E3</field3>
        <field4>E4</field4>
        <field5>E5</field5>
    </item>
</items>

如何使用XSLT做到这一点?我尝试过类似的事情:

<items>
    <xsl:apply-templates select="data[type='basic']"/>
</items>

<xsl:template match="data[type='basic']">
    <item>
        ...
    </item>
</xsl:template>

但是我不知道如何将相应的“额外”字段匹配到正确的item元素中。

1 个答案:

答案 0 :(得分:0)

首先请注意,type是一个属性,因此您需要使用@前缀来表示这一点

 <xsl:apply-templates select="data[@type='basic']"/>

然后,在与基本元素匹配的模板中,首先需要选择子节点...

<xsl:apply-templates />

然后,您需要选择后面的第一个data元素,但前提是它是一个“额外”元素

<xsl:apply-templates select="following-sibling::data[1][@type='extra']" />

然后,您将有一个模板来匹配“额外”模板,以输出其节点

<xsl:template match="data[@type='extra']">
  <xsl:apply-templates />
</xsl:template>

尝试使用此XSLT

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

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

  <xsl:template match="items">
    <items>
      <xsl:apply-templates select="data[@type='basic']"/>
    </items>
  </xsl:template>

  <xsl:template match="data[@type='basic']">
    <item>
      <xsl:apply-templates />
      <xsl:apply-templates select="following-sibling::data[1][@type='extra']" />
    </item>
  </xsl:template>

  <xsl:template match="data[@type='extra']">
    <xsl:apply-templates />
  </xsl:template>
</xsl:stylesheet>

请注意使用身份模板复制所有其他节点。 (如果您使用的是XSLT 3.0,请用<xsl:mode on-no-match="shallow-copy"/>代替)

另外请注意,您可以执行<xsl:apply-templates select="following-sibling::data[1][@type='extra']/*" />。这样,您就不需要“额外”模板了。

http://xsltfiddle.liberty-development.net/nc4NzR9上查看它的运行情况