XPath между двумя элементами - PullRequest
1 голос
/ 18 ноября 2011

У меня есть документ Word 2003 XML, в котором я пытаюсь найти определенные элементы. Мне удалось выполнить простые запросы XPath, чтобы найти отдельные элементы, но у меня возникают трудности с поиском запроса для поиска между двумя элементами:

    <w:r>
      <w:fldChar w:fldCharType="begin"/>
    </w:r>
    <w:r>
      <w:instrText> DOCPROPERTY  EvidenceBase  \* MERGEFORMAT </w:instrText>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="separate"/>
    </w:r>
    <w:r>
      <w:t>EvidenceBase</w:t>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="end"/>
    </w:r>

Я ищу вышеупомянутый XML, в котором есть aw: r с aw: fldChar, который имеет атрибут w: fldCharType со значением «begin».Он должен возвращать каждый элемент, пока не достигнет aw: r с aw: fldChar, который имеет атрибут w: fldCharType со значением «end».

Возможно ли это?

Ответы [ 3 ]

2 голосов
/ 18 ноября 2011
//w:r[preceding-sibling::w:r[w:fldChar/@w:fldCharType='begin'] and following-sibling::w:r[w:fldChar/@w:fldCharType='end']]

Помните, что префикс w должен быть привязан к правильному пространству имен для контекста пространства имен выражения XPath.Как это сделать, зависит от того, как вы используете XPath (XSLT, Java, C # ...).

Кроме того, это будет более сложно, если имеется несколько, возможно, вложенных маркеров «начало» и «конец».

1 голос
/ 07 ноября 2012

Если номер предшествующего начала отличается от количества концов, мы должны быть между началом и концом. Поэтому:

w:r[count(preceding-sibling::w:r[w:fldChar/@w:fldCharType='begin']) != count(preceding-sibling::w:r[w:fldChar/@w:fldCharType='end'])]
1 голос
/ 18 ноября 2011

В любой подобной задаче можно использовать формулу Кейсиана для пересечения набора узлов .

Если у нас есть два набора узлов $ns1 и $ns2, то все узлы, которые принадлежатоба набора узлов выбираются этим выражением XPath:

$ns1[count(.|$ns2) = count($ns2)]

В вашем случае вам нужно просто заменить $ns1 на :

//w:r[w:fldChar/@w:fldCharType='begin'][1]/following-sibling::*  

..

и замените $ns2 на :

//w:r[w:fldChar/@w:fldCharType='end'][1]/preceding-sibling::*  

Полученное выражение XPath может показаться слишком сложным, но вы получаете возможность очень легко решить любую такую ​​проблемуи почти механически:

  /*/w:r
      [w:fldChar/@w:fldCharType='begin']/following-sibling::*
     [count(. | /*/w:r[w:fldChar/@w:fldCharType='end']
                                     /preceding-sibling::*
            )
     =
      count(/*/w:r[w:fldChar/@w:fldCharType='end']
                                     /preceding-sibling::*)
     ]

проверка на основе XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="some:namespace">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
     <xsl:copy-of select=
     "/*/w:r
          [w:fldChar/@w:fldCharType='begin']/following-sibling::*
         [count(. | /*/w:r[w:fldChar/@w:fldCharType='end']
                                         /preceding-sibling::*
                )
         =
          count(/*/w:r[w:fldChar/@w:fldCharType='end']
                                         /preceding-sibling::*)
         ]
     "/>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к этому документу XML :

<t xmlns:w="some:namespace">
    <w:r>
      <w:fldChar w:fldCharType="before-begin"/>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="begin"/>
    </w:r>
    <w:r>
      <w:instrText> DOCPROPERTY  EvidenceBase  \* MERGEFORMAT </w:instrText>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="separate"/>
    </w:r>
    <w:r>
      <w:t>EvidenceBase</w:t>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="end"/>
    </w:r>
    <w:r>
      <w:fldChar w:fldCharType="after-end"/>
    </w:r>
</t>

точно требуемые элементы выбираются и копируются на выход :

<w:r xmlns:w="some:namespace">
   <w:instrText> DOCPROPERTY  EvidenceBase  \* MERGEFORMAT </w:instrText>
</w:r>
<w:r xmlns:w="some:namespace">
   <w:fldChar w:fldCharType="separate"/>
</w:r>
<w:r xmlns:w="some:namespace">
   <w:t>EvidenceBase</w:t>
</w:r>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...