通过重新排列节点来展平分层xml

时间:2015-09-09 15:14:03

标签: xml xslt xslt-1.0 hierarchy flatten

我需要压缩分层XML结构。现在这可能听起来像一个风化很好的主题,并且我已经倾注了许多链接。但它们主要是关于从扁平结构创建层次结构的建议。

输入XML -

<bom>
    <part>
        <name>a</name>
        <othernodes>abc</othernodes>
        <part>
            <name>b</name>
            <othernodes>abc</othernodes>
            <part>
                <name>e</name>
                <othernodes>abc</othernodes>
            </part>
            <part>
                <name>f</name>
                <othernodes>abc</othernodes>
            </part>
        </part>
        <part>
            <name>c</name>
            <othernodes>abc</othernodes>
            <part>
                <name>g</name>
                <othernodes>abc</othernodes>
            </part>
        </part>
        <part>
            <name>d</name>
            <othernodes>abc</othernodes>
        </part>
    </part>
</bom>

寻求输出 -

<bom>
    <part>
        <parent/>
        <name>a</name>
        <othernodes>abc</othernodes>
    </part>
    <part>
        <parent>a</parent>
        <name>b</name>
        <othernodes>abc</othernodes>
    </part>
    <part>
        <parent>a</parent>
        <name>c</name>
        <othernodes>abc</othernodes>
    </part>
    <part>
        <parent>a</parent>
        <name>d</name>
        <othernodes>abc</othernodes>
    </part>
    <part>
        <parent>b</parent>
        <name>e</name>
        <othernodes>abc</othernodes>
    </part>
    <part>
        <parent>b</parent>
        <name>f</name>
        <othernodes>abc</othernodes>
    </part>
    <part>
        <parent>c</parent>
        <name>g</name>
        <othernodes>abc</othernodes>
    </part>
</bom>

首先我认为这可能不可行。但后来我尝试想出某种xslt。我知道这里的递归是关键但不确定如何实现。这是我到目前为止的XSLT(显然它没有产生预期的结果)。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output encoding="UTF-8" indent="yes" method="xml" />

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

  <xsl:template match="bom">   
    <xsl:element name="bom">      
      <xsl:apply-templates select="@* | node() [not(child::part)]"/>      
      <xsl:apply-templates select="part"/>
      <!--<xsl:apply-templates select="part/child::part"/>-->
    </xsl:element>
  </xsl:template>

  <xsl:template match="part" >
    <xsl:element name="part">
      <xsl:element name="parent">
        <xsl:value-of select="../part/name"/>
      </xsl:element>
      <xsl:apply-templates select="@* | node() [not(part)]" />
      <xsl:apply-templates select="child::part"/>
    </xsl:element>    
  </xsl:template>
</xsl:stylesheet>

感谢是否有人可以就如何处理和解决此问题向我提供一些指示。 谢谢!

1 个答案:

答案 0 :(得分:1)

你几乎就在那里,你的样式表只需要一些装置(这里不需要递归):

  1. 指令<xsl:apply-templates select="@* | node() [not(child::part)]"/>应使用self::轴,以便正常工作。
  2. template match="part"中的说明必须在<xsl:element>
  3. 之外
  4. 未正确检索父名称 - 使用<xsl:value-of select="../name"/>代替<xsl:value-of select="../part/name"/>
  5. 考虑在输出结果树中的任何内容之前处理属性。
  6. 这是样式表的更正版本:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
        <xsl:output encoding="UTF-8" indent="yes" method="xml" />
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="bom">
            <xsl:element name="bom">      
                <xsl:apply-templates select="@* | node()"/>      
                <!--<xsl:apply-templates select="part/child::part"/>-->
            </xsl:element>
        </xsl:template>
    
        <xsl:template match="part" >
            <xsl:element name="part">
                <xsl:apply-templates select="@*"/>
                <xsl:element name="parent">
                    <xsl:value-of select="../name"/>
                </xsl:element>
                <xsl:apply-templates select="node() [not(self::part)]" />
            </xsl:element>    
            <xsl:apply-templates select="child::part"/>
        </xsl:template>
    </xsl:stylesheet>
    

    这是我获得的结果,与您在居住地提供的内容的主要区别在于元素不是以相同的方式排序:

    <?xml version="1.0" encoding="UTF-8"?>
    <bom>
       <part>
          <parent/>
          <name>a</name>
          <othernodes>abc</othernodes>
       </part>
       <part>
          <parent>a</parent>
          <name>b</name>
          <othernodes>abc</othernodes>
       </part>
       <part>
          <parent>b</parent>
          <name>e</name>
          <othernodes>abc</othernodes>
       </part>
       <part>
          <parent>b</parent>
          <name>f</name>
          <othernodes>abc</othernodes>
       </part>
       <part>
          <parent>a</parent>
          <name>c</name>
          <othernodes>abc</othernodes>
       </part>
       <part>
          <parent>c</parent>
          <name>g</name>
          <othernodes>abc</othernodes>
       </part>
       <part>
          <parent>a</parent>
          <name>d</name>
          <othernodes>abc</othernodes>
       </part>
    </bom>