我有一个XML文档,其结构类似于以下内容:
<article>
<header>
<metadata>
bunch of metadata nodes here
<abstract>
<p>this is one of the abstract's paragraphs</p>
</abstract>
</metadata>
</header>
<body>
<sec>
<title>This is title 1</title>
<p>Paragraph 1</p>
<p>paragraph 2</p>
<title>This is title 2</title>
<sec>
<title>This is title 3</title>
<p>paragraph 1 under title 3</p>
<p>paragraph 2 under title 3</p>
</body>
</article>
真正的XML肯定会比上面复杂得多,但它应该足以说明 .
我需要将特定模板仅应用于 <body>
元素内的第一个 <p>
元素 . 我可以轻松编写一个xpath表达式,为我感兴趣的节点选择:
(//body//p)[1]
不幸的是,这个xpath表达式不能用作XSLT中的匹配表达式
<xsl:template match="(//body//p)[1]">
<p_first>
<xsl:call-template name="copyElementAttributes" />
<xsl:apply-templates select="@*|node()" />
</p_first>
</xsl:template>
上面的模板在尝试通过XSL引擎运行时会抛出错误 . 是否有可用于选择元素的匹配表达式?
2 回答
你必须使用类似的东西
即在主体内找到
p
,其前面的其他p
元素的数量与开始<body>
标记前面的数字相同 .另外
会寻找一个没有任何前身
p
元素的p
,这些元素本身就是body
的后代 .ancestor::body
约束是必要的,因为每个body//p
前面都是abstract
内的p
. 如果可能有多个body
元素,它会变得更复杂,因为我们只检查body
元素内的p
,不一定是相同的body
.试试
match="body//p[not(preceding::p)]"
.