首页 文章

与XML文档中特定元素的第一个匹配项匹配的模板

提问于
浏览
2

我有一个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 回答

  • 1

    你必须使用类似的东西

    <xsl:template match="body//p[count(preceding::p) = count(ancestor::body/preceding::p)]">
    

    即在主体内找到 p ,其前面的其他 p 元素的数量与开始 <body> 标记前面的数字相同 .

    另外

    <xsl:template match="body//p[not(preceding::p[ancestor::body])]">
    

    会寻找一个没有任何前身 p 元素的 p ,这些元素本身就是 body 的后代 . ancestor::body 约束是必要的,因为每个 body//p 前面都是 abstract 内的 p . 如果可能有多个 body 元素,它会变得更复杂,因为我们只检查 body 元素内的 p ,不一定是相同的 body .

  • 3

    试试 match="body//p[not(preceding::p)]" .

相关问题