xslt - 使用 XSLT 进行位置分组

标签 xslt

我有一个包含一些文档的 xml:

<document>
    <line id="0">
        <field id="0"><![CDATA[H:doc1]]></field>
    </line>
    <line id="1">
        <field id="0"><![CDATA[L:1]]></field>
    </line>
    <line id="2">
        <field id="0"><![CDATA[L:2]]></field>
    </line>
    <line id="3">
        <field id="0"><![CDATA[L:3]]></field>
    </line>
    <line id="4">
        <field id="0"><![CDATA[H:doc2]]></field>
    </line>
    <line id="5">
        <field id="0"><![CDATA[L:1]]></field>
    </line> 
</document>

H=文档标题,L=行项目。在此示例中,有两个 H 表示两个文档,编号为 doc1 和 doc2。 doc1 有三个订单项,doc2 有一个订单项。

如何使用 xslt 版本 1 转换数据以获得此结果:

<documents>
    <document>
        <header>
            <number>doc1</number>
        </header>
        <line-item>
            <line-number>1</line-number>
            <line-number>2</line-number>
            <line-number>3</line-number>
        </line-item>
    </document>
    <document>
        <header>
            <number>doc2</number>
        </header>
        <line-item>
            <line-number>1</line-number>
        </line-item>
    </document>
</documents>

最佳答案

这个 XSLT 1.0 转换:

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

 <xsl:key name="kFollowing"
   match="line[starts-with(field,'L:')]"
   use="generate-id(preceding-sibling::line
                         [starts-with(field,'H:')]
                         [1]
                    )"/>

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

 <xsl:template match="line[starts-with(field,'H:')]">
  <document>
   <header>
    <number><xsl:value-of select="substring-after(field,'H:')"/></number>
    <line-item>
     <xsl:apply-templates mode="inGroup" select=
        "key('kFollowing', generate-id())"/>
    </line-item>
   </header>
  </document>
 </xsl:template>

 <xsl:template match="line" mode="inGroup">
  <line-number>
   <xsl:value-of select="substring-after(field,'L:')"/>
  </line-number>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<document>
    <line id="0">
        <field id="0"><![CDATA[H:doc1]]></field>
    </line>
    <line id="1">
        <field id="0"><![CDATA[L:1]]></field>
    </line>
    <line id="2">
        <field id="0"><![CDATA[L:2]]></field>
    </line>
    <line id="3">
        <field id="0"><![CDATA[L:3]]></field>
    </line>
    <line id="4">
        <field id="0"><![CDATA[H:doc2]]></field>
    </line>
    <line id="5">
        <field id="0"><![CDATA[L:1]]></field>
    </line>
</document>

产生想要的正确结果:

<documents>
   <document>
      <header>
         <number>doc1</number>
         <line-item>
            <line-number>1</line-number>
            <line-number>2</line-number>
            <line-number>3</line-number>
         </line-item>
      </header>
   </document>
   <document>
      <header>
         <number>doc2</number>
         <line-item>
            <line-number>1</line-number>
         </line-item>
      </header>
   </document>
</documents>

说明:使用按键方便地指定和选择“标题”之后的相邻“行”的完整组。

关于xslt - 使用 XSLT 进行位置分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6789838/

相关文章:

XSLT 1.0 和字符串计数

java - XSL - 匹配节点的文本并附加另一个节点作为同级节点

xml - 第一个最后一个元素

javascript - XSLT 在 IF 语句后添加书价

xml - 如何获取所有已使用命名空间的列表?

XSLT date-time() 函数在 ALTOVA XmlSpy 中未知

css - 通过 CSS 操作 xslt 菜单

xml - 帮助合并相邻节点

xml - XSLT:属性内的 'xsl:value-of'

xslt - 将子元素拆分为子部分