【问题标题】:how to get the next immediate following::node() <w:tbl> elements of the context node using xslt2.0?如何使用 xslt2.0 获取上下文节点的下一个紧随其后的::node() <w:tbl> 元素?
【发布时间】:2012-09-04 04:47:06
【问题描述】:

我想使用 xslt 2.0 将一种 xml 格式转换为另一种 xml 格式。现在我想获取上下文节点的下一个紧随其后的::node() 元素。例如,

这是我的 xml 文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                    xmlns:v="urn:schemas-microsoft-com:vml">
        <w:body>
      <w:p>para1</w:p>   <!-- assume this as context node  -->
      <w:tbl>table data 1</w:tbl>
      <w:tbl>table data 2</w:tbl>
      <w:p>para2</w:p>
      <w:tbl>table data 3</w:tbl>
      <w:tbl>table data 4</w:tbl>
      <w:tbl>table data 5</w:tbl>
      <w:tbl>table data 6</w:tbl>
      <w:p>para3</w:p>
   </w:body>
  </w:document>

所以,根据上述 xml 文件中提到的上下文节点,我只想选择表数据 1 和表数据 2。

例如,如果我的上下文节点是 para2,那么我只想选择表数据 3、表数据 4、表数据 5 和表数据 6。

所以,我写了这样的xslt,

<xsl:for-each select="following::node()/self::w:tbl">
     <xsl:choose>
         <xsl:when test="self::w:tbl">
             <xsl:apply-templates select="self::w:tbl"></xsl:apply-templates>
          </xsl:when>                                             
     </xsl:choose>                                         
</xsl:for-each>

但它产生了错误的结果......

请指导我摆脱这个问题...

【问题讨论】:

    标签: xml xslt xpath xslt-2.0 xpath-2.0


    【解决方案1】:

    这是一个可能有用的函数:

    <xsl:function name="f:adjacently-following" as="element()*">
      <xsl:param name="start" as="element()"/>
      <xsl:param name="elementName" as="xs:QName"/>
      <xsl:variable name="next" select="$start/following-sibling::*[1]"/>
      <xsl:if test="node-name($next) = $elementName">
          <xsl:sequence select="$next, f:adjacently-following($next, $elementName)"/>
      </xsl:if>
    </xsl:function>
    

    那你可以拨打f:adjacently-following(., xs:QName('w:tbl'))

    【讨论】:

      【解决方案2】:

      假设你被定位在一个 w:p 元素上,你可以获得以下所有 w:tbl 兄弟姐妹,它们的第一个最前面的 w:p 是当前元素

      <xsl:apply-templates 
         select="following-sibling::w:tbl
           [generate-id(preceding-sibling::w:p[1]) = generate-id(current())]" />
      

      这可以通过使用 xsl:key 稍微整理一下。如果您要定义以下键:

      <xsl:key name="tbl" match="w:tbl" use="generate-id(preceding-sibling::w:p[1])" />
      

      然后你可以像这样得到以下 w:tbl 元素:

      <xsl:apply-templates select="key('tbl', generate-id())" />
      

      例如,给定以下 XSLT

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
         xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
         xmlns:v="urn:schemas-microsoft-com:vml" exclude-result-prefixes="w v">
         <xsl:output method="xml" indent="yes"/>
      
         <xsl:key name="tbl" match="w:tbl" use="generate-id(preceding-sibling::w:p[1])" />
      
         <xsl:template match="w:body">
            <xsl:apply-templates select="w:p[1]" />
         </xsl:template>
      
         <xsl:template match="w:p">
            <xsl:apply-templates select="key('tbl', generate-id())" />
         </xsl:template>   
      
         <xsl:template match="w:tbl">
            <table><xsl:value-of select="." /></table>
         </xsl:template>
      </xsl:stylesheet>
      

      当应用于您的示例 XML 时,将输出以下内容:

      <table>table data 1</table>
      <table>table data 2</table>
      

      请注意这是一个 XSLT1.0 解决方案。可能还有其他仅适用于 XSLT2.0 的方法。

      【讨论】:

      • 谢谢蒂姆。你能告诉我我当前的上下文节点是否是 table data 1 那么它适用于这种情况吗?
      • 不,此解决方案仅在您当前的上下文是 w:p 元素时才有效。
      【解决方案3】:

      这个 XSLT 2.0 样式表...

      <xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
        xmlns:v="urn:schemas-microsoft-com:vml"
        exclude-result-prefixes="xsl w v">
      <xsl:output method="xml" indent="yes"/>
      <xsl:strip-space elements="*"/>
      
      <xsl:template match="/">
       <root>
         <xsl:for-each-group select="w:document/w:body/(w:p|w:tbl)" group-starting-with="w:p" >
          <p>
            <xsl:apply-templates select="current-group()" />
          </p>
         </xsl:for-each-group>
       </root>
      </xsl:template>
      
      <xsl:template match="w:tbl">
        <table>
          <xsl:value-of select="." />
        </table>
      </xsl:template>
      
      </xsl:stylesheet>
      

      ...应用于此输入文档时...

      <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:v="urn:schemas-microsoft-com:vml">
          <w:body>
              <w:p>para1</w:p>
              <!-- assume this as context node -->
              <w:tbl>table data 1</w:tbl>
              <w:tbl>table data 2</w:tbl>
              <w:p>para2</w:p>
              <w:tbl>table data 3</w:tbl>
              <w:tbl>table data 4</w:tbl>
              <w:tbl>table data 5</w:tbl>
              <w:tbl>table data 6</w:tbl>
              <w:p>para3</w:p>
          </w:body>
      </w:document>
      

      ...产量...

      <root>
         <p>para1<table>table data 1</table>
            <table>table data 2</table>
         </p>
         <p>para2<table>table data 3</table>
            <table>table data 4</table>
            <table>table data 5</table>
            <table>table data 6</table>
         </p>
         <p>para3</p>
      </root>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-12
        • 2012-10-12
        相关资源
        最近更新 更多