Разрезание большого XML-файла на маленькие куски - PullRequest
3 голосов
/ 30 января 2011

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

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

Ответы [ 4 ]

3 голосов
/ 30 января 2011

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

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

0 голосов
/ 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 , но мои знания не относятся к .NET, и я не могу сказать из документации, являются ли они будет работать точно так же, как и версия Java, которую я только что дал вам.

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

0 голосов
/ 30 января 2011

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

0 голосов
/ 30 января 2011

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

...