XSLT:只应用多个匹配模板中的一个?

时间:2016-02-25 22:15:59

标签: xml xslt

我在XSLT书中找不到这样的例子,但是,我真的不知道该找什么。我试过谷歌搜索,但我真的不知道如何制定搜索词。我尝试以不同的方式处理<p>个节点,具体取决于父节点。这是我的xml,大大简化了。

<body>
  <p>consequuntur magni dolores eos</p>        <!-- Needs one LF -->
  <p>numquam eius modi tempora</p>             <!-- Needs two LFs -->
  <ul>
    <li><p>aliquam quaerat voluptatem</p></li> <!-- Needs one LF -->
    <li><p>quis nostrum</p></li>               <!-- Needs two LFs -->
  </ul>
  <some><arbitrary><path><p>qui dolorem ipsum</p></path></arbitrary></some>
</body>

我对非任意<p>节点做得很好:

<xsl:template match="body/p[1] | li/p[1]">
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="body/p[position() > 1] | li/p[position() > 1]">
    <xsl:text>&#10;&#10;</xsl:text>
    <xsl:apply-templates/>
</xsl:template>

但我还需要一个适用于<p>的模板,以及我遇到麻烦的地方:<xsl:template match="p">也会应用于正文和li <p>节点。

似乎最直接的方法是以某种方式让处理器不要将任意<p>应用于所有内容,但我无法弄清楚如何做到这一点。我想也许可以在我的任意模板上添加类似*[not(self::body)]/p | *[not(self::li)]/p的东西,但那是一个联盟,我无法弄清楚如何得到一个交集。我已经看到了一些方法,包括迈克尔凯,但我无法理解这种符号,无论如何,我不确定它是最好的(正确吗?)这样做的方法。

2 个答案:

答案 0 :(得分:2)

您可能正在寻找priority属性。你可以,例如使用

<xsl:template match="p" priority="1">

<xsl:template match="body/p[1] | li/p[1]" priority="2">

<xsl:template match="body/p[position() > 1] | li/p[position() > 1]" priority="2">

答案 1 :(得分:2)

选择除pbody元素的直接子元素之外的所有li元素,可以通过单个谓词来实现。

  

* [not(self :: body)] / p | * [没有(个体:: LI)] / P

非常接近,但是|不是or-operator,而是你指出的联合。因此,选择所有p元素并检查它们是否不是body的孩子,而不是li的孩子。

<xsl:template match="p[not(../../body) and not(../../li)]">
    <xsl:text>...</xsl:text>
    <xsl:apply-templates/>
</xsl:template>

应用DeMorgan,这可以简化为

<xsl:template match="p[not(../../body or ../../li)]">
    <xsl:text>...</xsl:text>
    <xsl:apply-templates/>
</xsl:template>