XSLT 2.0,从后代递归获取名为enum的ancestor ::子元素

时间:2012-09-17 18:57:01

标签: xml xslt-2.0 data-conversion node-set nodesets

更新:2012年9月18日,下午晚些时候 101.(a)在这里是额外的,并且是我需要的祖先:: * [@ belcode]。它们位于下面的XML示例中,我无法弄清楚如何获取它们。

错误的XML输出示例:

<p style="I24">101.(a)(e)(1)(A) If the Attorney General determines that a licensee under this section has willfully violated any provision of this chapter or any regulation prescribed under this chapter, the Attorney General may&mdash;</p>

XSL,其中只有for-each与belcode表现不佳:

<xsl:choose>
<xsl:when test="../@display-inline='yes-display-inline'">

<xsl:for-each select="ancestor-or-self::*[@belcode!='' and not(../@belcode/text or ../@belcode/header)]/enum">      
<xsl:value-of select="."/>   
</xsl:for-each> 

<xsl:for-each select="ancestor-or-self::*[@display-inline='yes-display-inline']/enum">      
<xsl:value-of select="."/>   
</xsl:for-each> 
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../enum"/>
<xsl:text></xsl:text>
</xsl:otherwise>
</xsl:choose>

更新:2012年9月18日 我测试了你给我的代码,我的外部条件不起作用......而且,我使用的是XSLT 2.0,所以for-each不是必需的。

新的XML输出不是QUITE工作(太多的祖先),但我只在正确的p元素上使用它们:

<section number="101">
<title style="I72">SEC. 101. SECTION TITLE.</title>
<p style="I20">(a)cpk2 In General.&mdash;Section 923...</p>
<p style="I20">(e)</p>
<p style="I22">(1)</p>
<p style="I24">&ensp;&ensp;&ldquo;I 101. (a) (e) (1) (A)cpk1 If the ... may&mdash;</p>
<p style="I26">(i)cpk2 if the violation is of a minor nature&mdash;</p>
</section>

非常接近的XSLT代码,我“认为”这需要更多的工作。我需要从具有belcode属性的第一个祖先获取子枚举元素,返回到我的文本元素的父元素的枚举。

我认为我需要在值中替换*以及让我回到我想要的顶级祖先的东西,我只是对XPath / XSLT很新,并且与语法作斗争。

<xsl:choose>
<xsl:when test="../@display-inline='yes-display-inline' and ancestor::*/@belcode[1]">
<xsl:value-of select="ancestor-or-self::*/enum"/>
<xsl:text>cpk1</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../enum"/>
<xsl:text>cpk2</xsl:text>
</xsl:otherwise>
</xsl:choose>

提前感谢任何可能的建议。

如何从我的子条款文本节点上升树(我保证我没有命名元素文本),直到我找到具有代码的祖先,并且没有display-inline =“是 - 显示内联“,并让所有孩子”enum“包容?路上的所有祖先元素也没有标题或文本子元素,但确实有枚举。 (是的,有一个XML示例)。

背景:

我已将XML 输入嵌套到section / subsection / paragraph / subparagraph / clause (每个都可以有一个枚举,标题,文本子),它们被夷为平地 输出一个充满“p”的部分,其风格与以往不同 sublevels,其中“enum”,“header”,“text”都被放入“p”。

我遇到麻烦的地方是,在某些情况下,如下面的示例,只有一个或多个级别的枚举。输出段落应该得到FIRST级别的代码attr(转换为样式)而没有“header”或“text”,以及它之间的所有“enum”和具有“text”的级别,这是哪里“p”包装器得到输出,以便展平适当地发生。用英语说,我需要一个(p style =“P20”)(e)(1)(A)。

嵌套XML输入:

<section code="P72">
<enum>101.</enum>
<header>SECTION TITLE.</header>
<subsection code="P20">
<enum>(e)</enum>
<paragraph display-inline="yes-display-inline">
<enum>(1)</enum>
<subparagraph display-inline="yes-display-inline">
<enum>(A)</enum>
<text>If the ... may—</text>
<clause belcode="I24">
<enum>(i)</enum>
<text>if the violation is of a minor nature—</text>
</clause>
</subparagraph>
</paragraph>
</subsection>
</section>

期望的输出:

<section number="101">
<title style="I72">SEC. 101. SECTION TITLE.</title>
<p style="I20">(a) In General.&mdash;Section 923...</p>
<p style="I20">(e)(1)(A) If the ... may&mdash;</p>
<p style="I24">(i) if the violation is of a minor nature&mdash;</p>
</section>

我得到的输出:

<section number="101">
<title style="I72">SEC. 101. SECTION TITLE.</title>
<p style="I20">(a) In General.&mdash;Section 923...</p>
<p style="I20">(e)</p>
<p style="I22">(1)</p>
<p style="I24">(A) If the ... may&mdash;</p>
<p style="I26">(i) if the violation is of a minor nature&mdash;</p>
</section>

无效的XSL代码段:

<xsl:template match="//subparagraph/text">
<p><xsl:attribute name="style"><xsl:value-of select="parent::subparagraph/@code"/></xsl:attribute>
<xsl:choose>
<xsl:when test="ancestor::*/enum and not(boolean(ancestor::*/header) or boolean(ancestor::*/text))"><xsl:value-of select="ancestor-or-self::*/enum"/><xsl:text> </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../enum"/><xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</p><xsl:text>&#10;</xsl:text>
</xsl:when>
</xsl:template>

我意识到这只是//子段/文本片段,但它是需要显示输出枚举的部分,我知道如何将它们显示在其他地方,一旦我将它们放到我想要的地方。

1 个答案:

答案 0 :(得分:0)

我认为你必须在XSLT 1.0中工作,如果xsl:value-of元素被赋予多个节点作为参数,它将获取第一个元素的值并忽略其他元素。如果你在1.0,我想你可能想尝试替换

<xsl:when test="ancestor::*/enum 
                and not(boolean(ancestor::*/header) 
             or boolean(ancestor::*/text))">
  <xsl:value-of select="ancestor-or-self::*/enum"/>
  <xsl:text> </xsl:text>
</xsl:when>

<xsl:when test="ancestor::*/enum 
                and not(boolean(ancestor::*/header) 
                     or boolean(ancestor::*/text))">
  <xsl:for-each select="ancestor-or-self::*/enum">
     <xsl:value-of select="concat(., ' ')"/>
  </xsl:for-each>
</xsl:when>

N.B。未经测试(并且容易出错:我没有使用xsl:for-each因为我发现我犯了很多错误),所以请仔细测试。