как получить следующие немедленные следующие элементы:: node() ‹w:tbl› узла контекста, используя xslt2.0?

Я хочу преобразовать один формат xml в другой формат xml с помощью xslt 2.0. Теперь я хочу получить следующие немедленные следующие элементы:: 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>

Но это дало неверный результат...

Пожалуйста, помогите мне избавиться от этой проблемы...


person Saravanan    schedule 04.09.2012    source источник


Ответы (3)


Вот функция, которая может быть полезна:

<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'))

person Michael Kay    schedule 04.09.2012

Предполагая, что вы были расположены на элементе 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.

person Tim C    schedule 04.09.2012
comment
спасибо Тим. Не могли бы вы сказать мне, если мой текущий узел контекста — это ‹w:tbl›табличные данные 1‹/w:tbl›, то будет ли он работать в этой ситуации? - person Saravanan; 04.09.2012
comment
Нет, это решение будет работать, только если ваш текущий контекст является элементом w:p. - person Tim C; 04.09.2012

Эта таблица стилей 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>
person Sean B. Durkin    schedule 04.09.2012