xslt:以相反的顺序遍历祖先的链

时间:2014-11-11 12:24:07

标签: xml xslt xsd ancestor

假设我有以下xml文档:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="FirstLevel">
    <xs:unique name="uniqueL2inL1">
      <xs:selector xpath="SecondLevel" />
      <xs:field xpath="@Name" />
    </xs:unique>
  </xs:element>
  <xs:element name="SecondLevel">
    <xs:unique name="uniqueL3inL2">
      <xs:selector xpath="ThirdLevel" />
      <xs:field xpath="@Name" />
    </xs:unique>
  </xs:element>
  <xs:element name="ThirdLevel">
    <xs:unique name="uniqueL4inL3">
      <xs:selector xpath="FourthLevel" />
      <xs:field xpath="@Name" />
    </xs:unique>
  </xs:element>
  <xs:element name="FourthLevel"/>
</xs:schema>

有什么可能获得&#34;链&#34;从ThirdLevel元素到正确排序中的文档根目录中的唯一定义?

我想要ThirdLevel得到的结果,例如:

FirstLevel
SecondLevel

要获取FirstLevel的节点(例如root-element),我需要查询xs:element,其中xs:unique但其名称本身无法用于xs:unique/xs:selector/@xpath。此特定查询是:

<xsl:variable name="root-element" select="//xs:element[xs:unique and not(//xs:element/xs:unique/xs:selector/@xpath = @name)]/@name"/>

现在我需要在ThirdLevel和此$root-element之间获取所有节点。

我有一个带有两个参数的递归调用template(可以附加,但为了清楚起见,请放在一边),它输出所有节点。

是否可以使用一个xpath进行查询?

问候

1 个答案:

答案 0 :(得分:0)

我不确定整个方法对于复杂的模式和任意的XPath选择器是否有意义但是如果当前的方法为您提供所需的输出,只能以错误的顺序存储,那么您可以简单地将输出存储在变量中并反转该变量输出值时的内容:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" >
  <xsl:output method="text" />
  <xsl:template match="xs:element">
    <xsl:result-document href="chain_{@name}">
      <xsl:variable name="element-name" select="@name"/>
      <xsl:variable name="parent-name" select="//xs:unique/xs:selector[@xpath=$element-name]/@xpath"/>
      <xsl:if test="$parent-name != ''">
        <xsl:variable name="list" as="xs:string*">
          <xsl:call-template name="mytemplate">
            <xsl:with-param name="unique-block" select="//xs:unique/xs:selector[@xpath=$element-name]/.."/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="reverse($list)" separator="&#10;"/>
      </xsl:if>
    </xsl:result-document>
  </xsl:template>
  <xsl:template name="mytemplate">
    <xsl:param name="unique-block"/>
    <xsl:variable name="parent-name" select="$unique-block/../@name"/>
    <xsl:sequence select="$parent-name"/>
    <xsl:variable name="unique-selector" select="//xs:unique/xs:selector[@xpath=$parent-name]/@xpath"/>
    <!-- evaluate and recurse, if needed: -->
    <xsl:if test="$unique-selector != ''">
      <xsl:call-template name="mytemplate">
        <xsl:with-param name="unique-block" select="//xs:unique/xs:selector[@xpath=$parent-name]/.." />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>