Разрезание большого XML-файла на небольшие куски

У меня есть большой дамп википедии, который я хочу разрезать на разные файлы (по 1 файлу на каждую статью). Я написал приложение VB, чтобы сделать это за меня, но оно было довольно медленным и вышло из строя после нескольких часов резки. В настоящее время я разбиваю файл на более мелкие фрагменты по 50 МБ с помощью другого приложения, но это занимает много времени (20-30 минут для каждого фрагмента). Я должен быть в состоянии разрезать каждый из них по отдельности, если я это сделаю.

Есть ли у кого-нибудь предложения, как быстрее разрезать этот файл?


person James Austin    schedule 30.01.2011    source источник


Ответы (4)


Самый простой способ сделать это с помощью C# — с помощью XmlReader. Вы можете использовать только XmlReader для самой быстрой реализации или комбинировать с новыми классами LINQ XNode для достойного сочетания производительности и простоты использования. Пример см. в этой статье MSDN: http://msdn.microsoft.com/en-us/library/system.xml.linq.xnode.readfrom.aspx.

Вы должны иметь возможность модифицировать пример, чтобы хранить узел только для одного документа в памяти за раз, а затем записать его обратно в виде файла. Он должен хорошо работать и работать с очень большими файлами.

person jdasilva    schedule 30.01.2011

Я предполагаю, что вы используете парсер DOM. Для потенциально больших файлов всегда следует использовать парсеры SAX. Парсеры DOM считывают файл целиком в память, парсеры SAX считывают за раз как можно меньше и поэтому работают намного эффективнее. В этом руководстве описывается, как написать анализатор C# SAX, VB должен быть очень похож.

person kelloti    schedule 30.01.2011

Если бы я делал это на Java, я бы использовал javax.xml.stream.XMLEventReader и javax.xml.stream.XMLEventWriter.

В каком-то псевдокоде предположим, что тег <article> ограничивает каждую статью в Википедии, что вам не нужно беспокоиться о вложенных тегах <article>, и у вас есть функция openNewWriter() для открытия нового XMLEventWriter, который записывает в новый файл с подходящим именем. для этой статьи.

Тогда мой код будет выглядеть примерно так:

XMLEventReader r = // an XMLEventReader for the original wikipedia dump

XMLEventWriter w = null;

bool isInsideArticle = false;

while (r.hasNext()){
  XMLEvent e = r.nextEvent();

  if (e.isStartElement() &&
        e.asStartElement().getName().getLocalPart().equals("article")){
     w = openNewWriter();
     // write the stuff that belongs outside the <article> tag
     // by synthesizing XMLEvents and using w.add() to add them
     w.add(e);
     isInsideArticle = true;
  } else if (e.isEndElement() &&
           e.asEndElement().getName().getLocalPart().equals("article")) {
     w.add(e);
     // write the stuff that belongs outside the <article> tag
     // by synthesizing XMLEvents and using w.add() to add them
     isInsideArticle = false;
     w.close();
  } else if (isInsideArticle) {
     w.add(e);
  } else {
     // this tag gets dropped on the floor because it's not inside any article
  }
}

Теперь все, что вам нужно сделать, это найти потоковые XML-классы в .NET. Я думаю, что это system.xml.XMLReader и system.xml.XMLWriter, но мой опыт не t в .NET, и из документации я не могу сказать, будут ли они работать точно так же, как версия Java, которую я вам только что дал.

(Моя цель здесь больше показать вам, как подойти к проблеме, чем назвать вам имена классов, которые вам нужны.)

person Ken Bloom    schedule 01.02.2011

Вам следует попробовать vtd-xml для этого, у нас есть люди, которые говорят нам, насколько хорошо он работает для разделения больших файлов XML... http://www.codeproject.com/KB/XML/xml_processing_future.aspx нам также сказали, что DOM занимает вечность

person vtd-xml-author    schedule 30.01.2011