如何从XPath表达式中的谓词引用特定类型的兄弟XML节点?

时间:2015-05-22 04:04:36

标签: html xml xslt xpath

我正在使用XSLT样式表将简单的HTML文档转换为Unix手册页。我有一种情况,我想匹配一个文本节点,只有它紧跟在父节点中的<ul>兄弟节点之后。例如,这就是我想要转换的内容:

<html>
<body>

<dl>

  <dt>This is the first term to define.</dt>
  <dd>This is the first definition.</dd>

  <dt>This is the second term to define.</dt>
  <dd>This is the second definition, with a list in the middle:
  <ul>
    <li>This is the first item in the list.</li>
    <li>This is the second item in the list.</li>
  </ul>
  And now there's a sentence after the list.</dd>

</dl>

</body>
</html>

到目前为止,我有这个XSLT代码,它产生大部分正确的Unix手册页输出:

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

<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="html">
.TH "command" 1 "May 2015" "Package" "Organization"
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="ul">
.RS
<xsl:apply-templates select="child::node()"/>
.RE
</xsl:template>

<xsl:template match="li">
.IP \(bu 4
<xsl:apply-templates select="child::node()"/>
</xsl:template>

<xsl:template match="dl">
.P
<xsl:apply-templates select="child::node()"/>
</xsl:template>

<xsl:template match="dt">
.TP
<xsl:apply-templates select="child::node()"/>
<xsl:text>&#xa;</xsl:text>
</xsl:template>

<xsl:template match="dd">
<xsl:apply-templates select="child::node()"/>
</xsl:template>

<xsl:template match="li/text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>

<xsl:template match="dd//text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>

</xsl:stylesheet>

唯一的问题是,我还希望在<dd>节点内的文本节点上添加一个模板,该节点紧跟在<ul>节点之后,如下所示:

<xsl:template match="dd/text()[ ???? ]">
.IP
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>

问题在于我无法弄清楚在谓词(????)中放置什么内容,以便它只匹配紧跟<ul>之后的文本节点,如示例HTML代码中所示。我怀疑这很简单,但W3C XSLT定义文档的许多尝试和读数都没有帮助。

如果它有所不同,我在Java下使用XSLT 2.0和Saxon 9解析器,我运行如下:

  

java -cp saxon9he.jar net.sf.saxon.Transform test.html test.xsl

2 个答案:

答案 0 :(得分:1)

  

我无法弄清楚将什么放入谓词(????)中以便它   仅匹配紧跟<ul>

之后的文本节点

尝试:

<xsl:template match="dd/text()[preceding-sibling::node()[1][self::ul]]">

答案 1 :(得分:0)

您应该能够使用preceding-sibling::ul谓词来匹配公共父级中<ul>节点后面的节点:

dd/text()[preceding-sibling::ul]