1

我目前正在尝试通过获取其中的某些元素并遍历所选元素的祖先,将 XML 文件转换为多个输出 XML 文件。

例如:

源 XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <level_a> 
    <level_b> 
      <level_c> 
        <level_d> 
          <level_e/> 
        </level_d> 
      </level_c> 
    </level_b> 
    <level_b> 
      <level_c> 
        <level_d> 
          <level_e/> 
        </level_d> 
      </level_c> 
    </level_b> 
    <level_b> 
      <level_c> 
        <level_d> 
          <level_e/> 
          <level_e/> 
          <level_e/> 
        </level_d> 
      </level_c> 
    </level_b> 
    <level_b> 
      <level_c> 
        <level_d> 
          <level_d> 
            <level_e/> 
          </level_d> 
        </level_d> 
      </level_c> 
    </level_b>
  </level_a>
</root>

输出 XML 文件:

1:

 <output>
        <output level="b"> 
          <output level="c"> 
            <output level="d"> 
              <output level="e"/> 
            </output> 
          </output> 
        </output> 
 </output>

2:

 <output>
        <output level="b"> 
          <output level="c"> 
            <output level="d"> 
              <output level="e"/> 
            </output> 
          </output> 
        </output> 
 </output>

3:

 <output>
        <output level="b"> 
          <output level="c"> 
            <output level="d"> 
              <output level="e"/>
              <output level="e"/> 
              <output level="e"/>  
            </output> 
          </output> 
        </output> 
 </output>

4:

 <output>
      <output level="b"> 
        <output level="c"> 
          <output level="d"> 
            <output level="d"> 
              <output level="e"/> 
            </output> 
          </output> 
        </output> 
      </output>
 </output>

我知道我可以在使用以下 XPath 生成序列的行中做一些事情:

(//level_d[not(level_d)])[last()]/ancestor::*[self::level_c|self::level_b]

然后用 foreach 对其进行迭代,我将按文档顺序获得结果。

但我真正感兴趣的是,如何在不使用 foreach 的情况下实现相同的目标,我能想到的任何解决方案都会返回所有元素反转......

非常感谢任何提示

最好的问候
Vlax

4

2 回答 2

3

不知道为什么你会自下而上而不是自上而下。我会/*/*在那里匹配并创建结果文档。

例子...

XML 输入

<root>
    <level_a> 
        <level_b> 
            <level_c> 
                <level_d> 
                    <level_e/> 
                </level_d> 
            </level_c> 
        </level_b> 
    </level_a>
    <level_b> 
        <level_c> 
            <level_d> 
                <level_d> 
                    <level_e/> 
                </level_d> 
            </level_d> 
        </level_c> 
    </level_b>
</root>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>

    <xsl:template name="output">
        <output level="{substring-after(name(),'level_')}">
            <xsl:apply-templates/>
        </output>       
    </xsl:template>

    <xsl:template match="/*/*" priority="1">
        <xsl:result-document href="{generate-id()}.xml">
            <output>
                <xsl:call-template name="output"/>              
            </output>
        </xsl:result-document>
    </xsl:template>

    <xsl:template match="*[starts-with(name(),'level_')]">
        <xsl:call-template name="output"/>
    </xsl:template>

</xsl:stylesheet>

文件 1(名称会因为 不同而有所不同generate-id()

<output>
   <output level="a">
      <output level="b">
         <output level="c">
            <output level="d">
               <output level="e"/>
            </output>
         </output>
      </output>
   </output>
</output>

文件 2(名称会因为 不同而有所不同generate-id()

<output>
   <output level="b">
      <output level="c">
         <output level="d">
            <output level="d">
               <output level="e"/>
            </output>
         </output>
      </output>
   </output>
</output>
于 2013-06-04T21:39:44.660 回答
0

作为可变解决方案,如果 level_a 或 level_d 发生变化,您可以在此处调整值:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="//level_d[not(ancestor::level_d)]">
            <xsl:result-document href="{concat('file_', count(preceding::*[self::level_d])+1,'.xml')}">
                <output>
                    <xsl:apply-templates select="ancestor-or-self::node()[parent::level_a]" mode="output"></xsl:apply-templates>
                </output>
            </xsl:result-document>
    </xsl:template>

    <xsl:template match="*" mode="output">
        <output level="{substring-after(local-name(),'level_')}">
            <xsl:apply-templates mode="output"/>
        </output>
    </xsl:template>
</xsl:stylesheet>

它具有与预期相同的结果。

于 2013-06-04T23:56:32.050 回答