0

昨天我问了一个关于从 XSLT 动态加载外部 XML 的问题。它已被回答,但现在我有另一个问题。如果您阅读该问题,您将<include ref="/path/to/some.xml" />在第三级看到一个。如果<include>发生的级别不同怎么办?

有没有办法动态选择从 XML 中提取与原始文件中相同级别的节点?

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

合并.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>

水果.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>

香蕉.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>
4

1 回答 1

0

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

我将把这个问题留一会儿,也许有人有更好的解决方案。

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>
于 2013-05-22T18:09:39.317 回答