5

docxに似た形式のxmlファイルがあります。

<w:r>
  <w:rPr>
    <w:sz w:val="36"/>
    <w:szCs w:val="36"/>
  </w:rPr>
  <w:t>BIG_TEXT</w:t>
</w:r>

BIG_TEXT次のように、ソースxmlでのインデックスを取得する必要があります。

from lxml import etree
text = open('/devel/tmp/doc2/word/document.xml', 'r').read()

root = etree.XML(text)

start = 0
for e in root.iter("*"):
    if e.text:
        offset = text.index(e.text, start)
        l = len(e.text)
        print 'Text "%s" at offset %s and len=%s' % (e.text, offset, l)
        start = offset + l

index現在の+の位置から新しい検索を開始できますlen(text)が、別の方法はありますか?wたとえば、要素には1つの文字が含まれる場合があります。のインデックスは検索されますがw、タグテキストのインデックスは検索されませんw

4

1 に答える 1

9

私は同様の解決策を探していました(高速検索のために大きなxmlファイルのノードにインデックスを付けます)。

  • 私の知る限り、lxml不十分なソースラインのみを提供しています。Cf API :Original line number as found by the parser or None if unknown.
  • しかしexpat、ファイル内の正確なオフセットを提供します: CurrentByteIndex .
    • ハンドラーからフェッチされstart_element、タグの開始 (つまり'<') オフセットを返します。
    • ハンドラーからフェッチされ、データの開始 (例では) オフセットをchar_data返します。'B'

例 :

import xml.parsers.expat

# handler functions for parser events, and housekeeping.
class handler :
   def __init__(self, current_parser) :
      #tag of interest
      self.TARGET_TAG = "w:t"

      #set up parser
      self.parser = current_parser
      self.parser.StartElementHandler  = self.start_element
      self.parser.EndElementHandler    = self.end_element
      self.parser.CharacterDataHandler = self.char_data

      self.target_tag_met = False
      self.index = None

   def start_element(self, name, attrs):
      self.target_tag_met = (name == self.TARGET_TAG)

   def end_element(self, name) :
      self.target_tag_met = False

   def char_data(self, data):
      if self.target_tag_met :
         self.index = self.parser.CurrentByteIndex

#open file in binary mode for robuster byte offsets.
xmlFile = open("so_test.xml", 'rb')

p = xml.parsers.expat.ParserCreate()
h = handler(p)

p.ParseFile(xmlFile)
print (h.index)
于 2012-09-17T16:26:56.680 に答える