Каков наилучший способ использования Xpath для обработки больших файлов XML? - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть требование, когда я должен использовать большой XML (файл 4 ГБ) для поиска значений в нем. В основном я должен написать около 30 различных Xpath и сохранить значения в списке. Когда я пытаюсь проанализировать XML, выдается ошибка памяти. Я пытался использовать l xml и ElementTree с начальными и конечными событиями, но все же не повезло, что время обработки слишком велико, и мой ноутбук Pycharm / Jupyter выдает ошибку памяти.

Есть ли лучший способ сделать это ? Хотя эта реализация не ограничена каким-либо языком программирования, я предпочитаю Python, потому что это моя правая рука. Заранее спасибо.

Например, поиск: если я хочу указать год, в котором категория готовит. Затем я использую ./bookstore[@category=cooking]/book/year. Таким образом, значение равно 2005

Точно так же я должен найти значения моих тегов на основе моих бизнес-требований. В моем требовании XML не так просто, как в примере ниже.

<?xml version="1.0" encoding="UTF-8"?>

<bookstore>

<book category="cooking">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>

<book category="children">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

<book category="web">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>

</bookstore>

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

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

from simplified_scrapy import SimplifiedDoc,req,utils
def getBook(lines,category,year):
  html = "".join(lines)
  book = SimplifiedDoc(html).book
  if book.category==category and book.year.text==year:
    return book.category,book.title.text,book.authors.text,book.year.text,book.price.text
lst = []
with open('bookstore.xml', 'r') as file: # bookstore.xml is your xml file path
  lines = []
  flag = False
  for line in file:
    if flag or line.find('<book ')>=0:
      flag = True
      lines.append(line)
    if line.find('</book>')>=0:
      b = getBook(lines,'web','2003')
      if b: 
        lst.append(b)
        break # If you only want the first one, add a break
      flag = False
      lines = []
print (lst)

Результат:

[('web', 'XQuery Kick Start', ['James McGovern', 'Per Bothner', 'Kurt Cagle', 'James Linn', 'Vaidyanathan Nagarajan'], '2003', '49.99')]
0 голосов
/ 16 апреля 2020

В приведенном примере проблема может быть легко решена с использованием потоковой передачи в XSLT 3.0:

<xsl:mode streamable="yes">
<xsl:template match="book[@category='cooking']">
  <xsl:value-of select="year"/>
</xsl:template>

Я знаю, что этот пример является упрощением, но мы можем только судить, являются ли реальные данные / запрос пригодными для потока видя реальные данные / запрос. Дьявол кроется в деталях.

...