1

取得するテキストがこのような複数のノードにディスパッチされる「順序付けられた」xml ファイルで検索を行う必要があります。

<root>
    <div id="1">Hello</div>
    <div id="2">Hel</div>
    <div id="3">lo dude</div>   
    <div id="4">H</div>
    <div id="5">el</div>
    <div id="6">lo</div>
</root>

連結されたテキストに対して検索を行う必要があります。

HelloHello dudeHello

しかし、ノードの属性を取得できる必要があります。たとえば、「ll」検索の場合、ノードを取得したい:

<div id="1">Hello</div>
<div id="2">Hel</div>
<div id="3">lo dude</div>   
<div id="5">el</div>
<div id="6">lo</div>

または少なくともID。

誰かがXPathでこれを行う方法、または他の手段を知っていますか?

ちょっと難しいと思います。今のところ (単純な) アイデアはありません。ご協力いただきありがとうございます。

編集:検索が重要な情報であり、正確でなければならない前に、テキストを連結する必要があります!

4

2 に答える 2

0

XPath 2 では、トークン化を使用して、検索されたテキストが発生する頻度をカウントし、各ノードをテストできます。テキストにこのノードを含めない場合は、発生回数を減らします。数が減る場合、そのノードを結果に含める必要があります。それはそれほど速くはありません。

例のように、直接の子ノードのテキストのみが重要であると仮定すると、次のようになります。

for $searched in "ll" 
return //*/ for $matches in count(tokenize(string-join(*, ""), $searched)) - 1
            return *[$matches > count(tokenize(concat(" ",string-join(preceding-sibling::*, "")), $searched)) +
                                count(tokenize(concat(" ",string-join(following-sibling::*, "")), $searched)) - 2]
于 2013-04-13T00:12:21.717 に答える
0

「要素のラップ」は検索トークン内の任意のポイントで発生し、場合によっては複数の要素にまたがる可能性があるため、更新要件によって問題はさらに複雑になります。XPath < 3.0 でクエリを作成できるとは思いません (とにかく XPath でしかクエリを実行できない場合)。これには、XPath を拡張した XQuery を使用しました。コードはBaseXで正常に動作していますが、他のすべての XQuery エンジンでも動作するはずです (おそらく XQuery 3.0 が必要ですが、それは見ていません)。

コードはかなり複雑になりました。理解できるように十分なコメントを入れたと思います。ノードが次の要素内にある必要がありますが、わずかな調整により、任意の XML 構造をトラバースするためにも使用できます ( <span/>s やその他のマークアップを含む HTML を考えてみてください)。

(: functx dependencies :)
declare namespace functx = "http://www.functx.com";
declare function functx:is-node-in-sequence 
  ( $node as node()? ,
    $seq as node()* )  as xs:boolean {

   some $nodeInSeq in $seq satisfies $nodeInSeq is $node
 } ;
declare function functx:distinct-nodes 
  ( $nodes as node()* )  as node()* {

    for $seq in (1 to count($nodes))
    return $nodes[$seq][not(functx:is-node-in-sequence(
                                .,$nodes[position() < $seq]))]
 } ;

declare function local:search( $elements as item()*, $pattern as xs:string) as item()* {
  functx:distinct-nodes(
    for $element in $elements
    return ($element[contains(./text(), $pattern)], local:start-search($element, $pattern))
  )
};

declare function local:start-search( $element as item(), $pattern as xs:string) as item()* {
    let $splits := (
      (: all possible prefixes of search token :)
      for $i in 1 to string-length($pattern) - 1
      (: check whether element text starts with prefix :)
      where ends-with($element/text(), substring($pattern, 1, $i))
      return $i
    )
    (: go on for all matching prefixes :)
    for $split in $splits
    return
      (: recursive call to next element :)
      let $continue := local:continue-search($element/following-sibling::*[1], substring($pattern, $split+1))
      where not(empty($continue))
      return ($element, $continue)
};

declare function local:continue-search( $element as item()*, $pattern as xs:string) as item()* {
  if (empty($element)) then () else
  (: case a) text node contains whole remaining token :)
  if (starts-with($element/text(), $pattern))
  then ($element)
  (: case b) text node is part of token :)
  else if (starts-with($pattern, $element/text()))
  then
    (: recursive call to next element :)
    let $continue := local:continue-search($element/following-sibling::*[1], substring($pattern, 1+string-length($element/text())))
    where not(empty($continue))
    return ($element, $continue)
  (: token not found :)
  else ()
};

let $token := 'll'
return local:search(//div, $token)
于 2013-04-12T21:48:34.437 に答える