【问题标题】:XSLT 2.0: Flat XML to arbitrary hierarchical XML, if attribute = attribute thenXSLT 2.0:平面 XML 到任意分层 XML,如果属性 = 属性,则
【发布时间】:2014-12-23 11:07:17
【问题描述】:

我有一个具有平面层次结构的 XML 文档,必须将其转换为层次结构的 XML 文档:

首先是一个XML源文档的例子:

<group id="xyz">
   <name>bla</name>
   <part id="abc1"><name>blabla-1</name></part>
   <part id="abc2"><name>blabla-2</name></part>
   <part id="abc3"><name>blabla-3</name></part>
   <part id="abc4"><name>blabla-4</name></part>
   <part id="abc5"><name>blabla-5</name></part>
   <part id="abc6"><name>blabla-6</name></part>
   <part id="abc7"><name>blabla-7</name></part>
   <part id="abc8"><name>blabla-8</name></part>
</group>
<group id="abc4">
   <name>blabla-4</name>
   <part id="abc9"><name>blabla-9</name></part>
   <part id="abc10"><name>blabla-10</name></part>
   <part id="abc11"><name>blabla-11</name></part>
   <part id="abc12"><name>blabla-12</name></part>
   <part id="abc13"><name>blabla-13</name></part>
   <part id="abc14"><name>blabla-14</name></part>
   <part id="abc15"><name>blabla-15</name></part>
   <part id="abc16"><name>blabla-16</name></part>
</group>
<group id="abc10">
   <name>blabla-10</name>
   <part id="abc17"><name>blabla-17</name></part>
   <part id="abc18"><name>blabla-18</name></part>
   <part id="abc19"><name>blabla-19</name></part>
   <part id="abc20"><name>blabla-20</name></part>
   <part id="abc21"><name>blabla-21</name></part>
   <part id="abc22"><name>blabla-22</name></part>
   <part id="abc23"><name>blabla-23</name></part>
   <part id="abc24"><name>blabla-24</name></part>
</group>

以下是目标 XML 文档的示例:

<group id="xyz">
   <name>bla</name>
   <part id="abc1"><name>blabla-1</name></part>
   <part id="abc2"><name>blabla-2</name></part>
   <part id="abc3"><name>blabla-3</name></part>
   <group id=abc4">
      <name>blabla-4</name>
      <part id="abc9"><name>blabla-9</name></part>
         <group id="abc10">
         <name>blabla-10</name>
            <part id="abc17"><name>blabla-17</name></part>
            <part id="abc18"><name>blabla-18</name></part>
            <part id="abc19"><name>blabla-19</name></part>
            <part id="abc20"><name>blabla-20</name></part>
            <part id="abc21"><name>blabla-21</name></part>
            <part id="abc22"><name>blabla-22</name></part>
            <part id="abc23"><name>blabla-23</name></part>
            <part id="abc24"><name>blabla-24</name></part>
         </group>
      <part id="abc11"><name>blabla-11</name></part>  
      <part id="abc12"><name>blabla-12</name></part>
      <part id="abc13"><name>blabla-13</name></part>
      <part id="abc14"><name>blabla-14</name></part>
      <part id="abc15"><name>blabla-15</name></part>
      <part id="abc16"><name>blabla-16</name></part>
   </group>
</group>

【问题讨论】:

  • 为什么part的id为abc5abc6等的元素不在group id="xyz"的结果输出中?一旦找到引用group(如abc4)的part,是否要停止处理part 元素?
  • 您的第一个问题是您的“XML 源文档”不是 XML 文档,因为它缺少根级元素。
  • 致 Martin Honnen:不,我忘了在示例中添加 abc5-abc8(真丢脸!)它不应该在那里停止进程……对于 Ian Roberts:对于我离开的示例出根文档,真正的文档有一个根元素,所以再次,我的错误-_-感谢到目前为止的答案!

标签: xml xslt recursion hierarchy


【解决方案1】:

如果您只是使用

处理任何引用的组
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="2.0">

<xsl:param name="start-id" as="xs:string" select="'xyz'"/>

<xsl:output indent="yes"/>

<xsl:key name="gid" match="group" use="@id"/>

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

<xsl:template match="/*">
  <xsl:copy>
    <xsl:apply-templates select="key('gid', $start-id)"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="part[key('gid', @id)]">
  <xsl:apply-templates select="key('gid', @id)"/>
</xsl:template>

</xsl:stylesheet>

然后是输入的结果

<groups>
<group id="xyz">
   <name>bla</name>
   <part id="abc1"><name>blabla-1</name></part>
   <part id="abc2"><name>blabla-2</name></part>
   <part id="abc3"><name>blabla-3</name></part>
   <part id="abc4"><name>blabla-4</name></part>
   <part id="abc5"><name>blabla-5</name></part>
   <part id="abc6"><name>blabla-6</name></part>
   <part id="abc7"><name>blabla-7</name></part>
   <part id="abc8"><name>blabla-8</name></part>
</group>
<group id="abc4">
   <name>blabla-4</name>
   <part id="abc9"><name>blabla-9</name></part>
   <part id="abc10"><name>blabla-10</name></part>
   <part id="abc11"><name>blabla-11</name></part>
   <part id="abc12"><name>blabla-12</name></part>
   <part id="abc13"><name>blabla-13</name></part>
   <part id="abc14"><name>blabla-14</name></part>
   <part id="abc15"><name>blabla-15</name></part>
   <part id="abc16"><name>blabla-16</name></part>
</group>
<group id="abc10">
   <name>blabla-10</name>
   <part id="abc17"><name>blabla-17</name></part>
   <part id="abc18"><name>blabla-18</name></part>
   <part id="abc19"><name>blabla-19</name></part>
   <part id="abc20"><name>blabla-20</name></part>
   <part id="abc21"><name>blabla-21</name></part>
   <part id="abc22"><name>blabla-22</name></part>
   <part id="abc23"><name>blabla-23</name></part>
   <part id="abc24"><name>blabla-24</name></part>
</group>
</groups>

<groups>
   <group id="xyz">
      <name>bla</name>
      <part id="abc1">
         <name>blabla-1</name>
      </part>
      <part id="abc2">
         <name>blabla-2</name>
      </part>
      <part id="abc3">
         <name>blabla-3</name>
      </part>
      <group id="abc4">
         <name>blabla-4</name>
         <part id="abc9">
            <name>blabla-9</name>
         </part>
         <group id="abc10">
            <name>blabla-10</name>
            <part id="abc17">
               <name>blabla-17</name>
            </part>
            <part id="abc18">
               <name>blabla-18</name>
            </part>
            <part id="abc19">
               <name>blabla-19</name>
            </part>
            <part id="abc20">
               <name>blabla-20</name>
            </part>
            <part id="abc21">
               <name>blabla-21</name>
            </part>
            <part id="abc22">
               <name>blabla-22</name>
            </part>
            <part id="abc23">
               <name>blabla-23</name>
            </part>
            <part id="abc24">
               <name>blabla-24</name>
            </part>
         </group>
         <part id="abc11">
            <name>blabla-11</name>
         </part>
         <part id="abc12">
            <name>blabla-12</name>
         </part>
         <part id="abc13">
            <name>blabla-13</name>
         </part>
         <part id="abc14">
            <name>blabla-14</name>
         </part>
         <part id="abc15">
            <name>blabla-15</name>
         </part>
         <part id="abc16">
            <name>blabla-16</name>
         </part>
      </group>
      <part id="abc5">
         <name>blabla-5</name>
      </part>
      <part id="abc6">
         <name>blabla-6</name>
      </part>
      <part id="abc7">
         <name>blabla-7</name>
      </part>
      <part id="abc8">
         <name>blabla-8</name>
      </part>
   </group>
</groups>

【讨论】:

  • 如果您没有特定的组 ID 开始,您可以通过定义一个第二个键&lt;xsl:key name="pid" match="part" use="@id"/&gt;,然后使初始apply-templates select="group[not(key('pid', @id))]"
  • @IanRoberts,我同意你的建议,但会等到发帖人确定整个方法是否符合要求。
  • 谢谢大家的回答。我会尽快尝试并提供一些反馈。首先,我将尝试追溯 Martin Honnen 的脚本——这实际上是结果应该是的样子。伊恩·罗伯茨的暗示很好。由于它是一个零件列表,因此总会有一个具有特定 ID 的组,其中包含所有后续组和零件。但我会牢记第二个关键建议并尝试一下 - 但首先要提出建议的脚本,非常感谢 Martin Honnen!
  • 好的,我修改了这个例子,它工作得很好,再次感谢。但只是另一个问题:这是 muenchian 分组解决方案吗?使用 XSLT 2.0,您更愿意使用按功能分组,对吗?
  • 不,一个键用于有效地跟踪输入 XML 中的交叉引用,这不是分组。所以在 XSLT 1.0 或 2.0 或 3.0 中,我认为使用 key 就足够了。 Muenchian 分组也使用密钥,但方式不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-19
相关资源
最近更新 更多