2013-05-22 19 views
0

昨天我询问a question关于从XSLT动态加载外部XML。有人回答,但现在我有另一个问题。如果你阅读这个问题,你会在第三级看到<include ref="/path/to/some.xml" />。如果<include>发生的等级会发生什么变化呢?在XSLT中,是否可以跟踪路径并动态使用它?

是否有一种方法可以动态地选择从原始文件中出现的同一级别上的XML中提取节点?

编辑: 要明确:我说的是在XML中的“元素路径”(在XML中包含元素的位置),而不是文件路径。

merge.xslt:

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

    <xsl:output indent="yes" method="xml" encoding="utf-8" 
    omit-xml-declaration="yes" /> 

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

    <xsl:template match="include"> 
     <!-- the depth of the extraction path (fruit/*/*/*... etc) should 
      be based on the position of the matched <include> element --> 
     <xsl:apply-templates select="document(@ref)/fruit/*/*/*"/> 
    </xsl:template> 
</xsl:stylesheet> 

fruit.xml:

<fruit> 
    <local> 
    <apples> 
     <include ref="apples.xml" /> 
    </apples> 
    </local> 
    <exotic> 
    <bananas> 
     <deeperlevel> 
     <include ref="bananas.xml" /> 
     </deeperlevel> 
    </bananas> 
    <oranges> 
     <include ref="oranges.xml" /> 
    </oranges> 
    </exotic> 
</fruit> 

bananans.xml:

<fruit> 
    <exotic> 
    <bananas> 
     <deeperlevel> 
     <banana type="chiquita" color="yellow" /> 
     <banana type="generic" color="yellow" /> 
     </deeperlevel> 
    </bananas> 
    </exotic> 
</fruit> 

结果:

<fruit> 
    <local> 
    <apples> 
     <apple type="jonagold" color="red"/><apple type="granny-smith" color="green"/> 
    </apples> 
    </local> 
    <exotic> 
    <bananas> 
     <deeperlevel> 
     <deeperlevel> <!-- I don't want the second <deeperlevel> here, instead 
          <bananas .../> should be extracted, right after the 
          first <deeperlevel> --> 
      <banana type="chiquita" color="yellow"/> 
      <banana type="generic" color="yellow"/> 
     </deeperlevel> 
     </deeperlevel> 
    </bananas> 
    <oranges> 
     <orange type="juice-orange" color="orange"/><orange type="red-orange" color="red"/> 
    </oranges> 
    </exotic> 
</fruit> 
+0

你指的是水平,当谈到的步骤在'ref'属性值(即'/路径/到/ some.xml')的数量?或者你在谈论“include”元素的位置?在后一种情况下,建议的解决方案应该可以工作,它可以简单地匹配任何'include'元素,与它所发生的嵌套级别无关。您可能需要发布一个新的XML输入样本,并且想要向我们解释哪些结果需要额外的要求你的脸。 –

+0

我编辑了我的问题,它是关于从外部XML文档中提取的元素的选择,它们已经结束在输出XML中的正确位置。 – pancake

回答

0

我找到了解决我的问题的方法。这不是非常好的恕我直言,因为它是一个“eval”型解决方案,但它的工作原理。我在this question的回答中对我的问题应用了第三个建议,动态XPath评估扩展(dyn:evaluate())。幸运的是libxslt库(通过macports安装,版本1.1.27)的xsltproc工具支持它。

我打算让问题开放一段时间,也许有人有更好的解决方案。

XSLT:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:dyn="http://exslt.org/dynamic" 
    extension-element-prefixes="dyn"> 

    <xsl:output indent="yes" method="xml" encoding="utf-8" 
    omit-xml-declaration="yes" /> 

    <xsl:template match="@*|node()"> 
    <xsl:param name="depth" select="'/*'" /> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"> 
     <xsl:with-param name="depth" select="concat($depth, '/*')" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="include"> 
    <xsl:param name="depth" /> 
    <xsl:apply-templates select="dyn:evaluate(concat('document(@ref)', $depth))"> 
     <xsl:with-param name="depth" select="$depth" /> 
    </xsl:apply-templates> 
    </xsl:template> 

</xsl:stylesheet> 
相关问题