如何提高XSLT效率

时间:2016-11-15 08:17:53

标签: xml xslt xpath

我有一个像这样的XML文件:

我认为您可以将我的XML理解为内容表 AElement @Name='1'是条目 1
第一个AElement @Name='2'将是 1.1 AElement @Name='3'下面的AElement @Name='2'将直接属于它,使其输入 1.1.1 ,条目 1.1.2 和条目 1.1。 3 和条目 1.1.4
第二个AElement @Name='2'将是 1.2 等等..

<ROOT>
    <AElement Name="1">
        <AElement>
          <Child1></Child1>
          <Child2>0000</Child2>
        </AElement>
    </AElement> 
    <AElement Name="2">
        <AElement>
          <Child1>E</Child1>
          <Child2>1000</Child2>
        </AElement>
    </AElement> 
    <AElement Name="3">
        <AElement>
          <Child1>E</Child1>
          <Child2>0100</Child2>
        </AElement>
    </AElement> 
    <AElement Name="3">
        <AElement>
          <Child1>U</Child1>
          <Child2>0200</Child2>
        </AElement>
    </AElement> 
    <AElement Name="3">
        <AElement>
          <Child1>E</Child1>
          <Child2>0300</Child2>
        </AElement>
    </AElement> 
    <AElement Name="2">
        <AElement>
          <Child1>E</Child1>
          <Child2>2000</Child2>
        </AElement>
    </AElement> 
    <AElement Name="3">
        <AElement>
          <Child1>N</Child1>
          <Child2>0400</Child2>
        </AElement>
    </AElement> 
    <AElement Name="3">
        <AElement>
          <Child1>E</Child1>
          <Child2>0500</Child2>
        </AElement>
    </AElement>   
    <AElement Name="2">
        <AElement>
          <Child1>E</Child1>
          <Child2>3000</Child2>
        </AElement>
    </AElement>
    <AElement Name="2">
        <AElement>
          <Child1>U</Child1>
          <Child2>4000</Child2>
        </AElement>
    </AElement> 
    <AElement Name="3">
        <AElement>
          <Child1>E</Child1>
          <Child2>0600</Child2>
        </AElement>
    </AElement> 
    <AElement Name="4">
        <AElement>
          <Child1>E</Child1>
          <Child2>0010</Child2>
        </AElement>
    </AElement>
</ROOT>

通缉结果:

对于每个AElement,应创建一个表格 以下步骤的每个AElement的位置
如果是AElement/Child1='E'的{​​{1}} 应创建表格行和表格单元格 此表格单元格应填充AElement的{​​{1}}值。

但是,只有在AElement/Child2的以下步骤中有任何AElement时才能创建此表。

示例

对于每个AElement,应创建一个表  属于AElement/Child1='E'的每个AElement @Name='2'的位置 如果AElement @Name='3' AElement @Name='2'  应创建表行和表格单元格  此表格单元格应填充AElement/Child1='E'的{​​{1}}值。

所以这个:

AElement @Name='3'

成为这个:

AElement/Child2

但是这个:

AElement @Name='3'

不会创建表格,因为STEP 3000没有跟随<AElement Name="2"> <AElement> <Child1>U</Child1> <Child2>4000</Child2> </AElement> </AElement> <AElement Name="3"> <AElement> <Child1>E</Child1> <Child2>0600</Child2> </AElement> </AElement> <AElement Name="4"> <AElement> <Child1>E</Child1> <Child2>0010</Child2> </AElement> </AElement>

<fo:block>STEP 2  4000</fo:block>

<fo:table>
    <fo:table-row>
        <fo:table-cell>
            <fo:block>
                0600
            </fo:block>
        </fo:table-cell>
    </fo:table-row>
</fo:table>
<AElement Name="2">
    <AElement>
        <Child1>E</Child1>
        <Child2>3000</Child2>
    </AElement>
</AElement>
<AElement Name="2">
    <AElement>
        <Child1>U</Child1>
        <Child2>4000</Child2>
    </AElement>
</AElement>

@Tomalak的此代码返回想要的结果。

1 个答案:

答案 0 :(得分:1)

由于您只提供一个示例而没有进一步的背景,因此并非100%明确您的预期输出。

我正在做出如下猜测:

  1. 所有元素都在输入中正确预订。
  2. 您有多个<AElement Name="1">,每个<fo:block>STEP N</fo:block>开始一个新的&#34;部分&#34;。
  3. 在每个&#34;部分&#34;你想要多个<AElement>,其中N是每个@Name = '2'的@Name。
  4. 每个组都应包含属于 next 序号位置的元素(即STEP 1应包含具有<fo:table>的元素,依此类推)。这使得总共8组(N <= 8)。
  5. 在每个组中,您希望<AElement>包含M行,其中M是具有正确@Name且包含<Child1>E</Child1>的{​​{1}}项目数。
  6. 上述所有内容都需要是XSLT 1.0
  7. 所以处理的一般顺序是

      每个AElement[@Name = '1']
      • 表示N = 1 .. 8
        • 输出<fo:block>STEP N</fo:block>
        • 输出<fo:table> with M rows for group (N+1) </fo:table>

    我没有一个真实的5000元素输入XML来测试,但是我将在XSLT 1.0中解决这个问题。

    <xsl:transform version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:fo="http://www.w3.org/1999/XSL/Format" 
    >
        <xsl:output indent="yes" />
    
        <!-- all <AElement> we consider for output, indexed by their @Name and group ID -->
        <xsl:key name="AElementGroup" match="AElement[AElement/Child1 = 'E']" use="
            concat(@Name, '|', generate-id(preceding-sibling::AElement[@Name = '1'][1]))
        " />
    
        <!-- some random nodes, so we have something to count with -->
        <xsl:variable name="counter" select="(//node())[position() &lt; 9]" />
    
        <xsl:template match="/">
            <fo:root>
                <xsl:apply-templates select="ROOT" />
            </fo:root>
        </xsl:template>
    
        <xsl:template match="ROOT">
            <xsl:for-each select="AElement[@Name = '1']">
                <xsl:variable name="groupId" select="generate-id()" />
                <xsl:for-each select="$counter">
                    <xsl:variable name="groupKey" select="concat(position() + 1, '|', $groupId)" />
                    <fo:block><xsl:value-of select="concat('STEP ' , position())" /></fo:block>
                    <fo:table>
                        <fo:table-body>
                            <xsl:apply-templates select="key('AElementGroup', $groupKey)/AElement" />
                        </fo:table-body>
                    </fo:table>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:template>
    
        <xsl:template match="AElement/AElement">
            <fo:table-row>
                <fo:table-cell>
                    <fo:block><xsl:value-of select="Child2"/></fo:block>
                </fo:table-cell>
            </fo:table-row>
        </xsl:template>
    
    </xsl:transform>
    

    在进一步详细介绍建议的解决方案之前,请先提供一些反馈,了解这是否可以抓住您的任务。