Как проанализировать один и тот же элемент нескольких файлов одновременно в Perl - PullRequest
0 голосов
/ 22 июля 2010

Я хочу объединить несколько файлов XML в Perl.Каждый файл состоит из множества элементов;Мне нужно объединить данные с одним и тем же элементом из этих файлов.например,

file1 имеет элементы {e1, e2, e4}

file2 имеет элементы {e1, e3, e4}

file3 имеет элементы {e2, e4, e5}

, поэтому мне нужно объединить e1 файла1 с e1 файла2, объединить e2 файла1 и e2 файла3 и т. Д. Объединенный результат будет сохранен в другом файле.

Поскольку размер этих файловфайлы большие, поэтому объединять файл данных по файлу нехорошо, т. е. анализировать весь файл1, затем анализировать весь файл2 и объединять его с файлом1.и т.д., потому что это потребует много памяти.

Так что я планирую объединить данные элемент за элементом.т.е. анализирует все файлы e1, освобождает память, затем анализирует элемент2 всех файлов, освобождает память и т. д.

В настоящее время я использую xml: parser: sax parser для анализа и обработки файлов.

Мой вопрос заключается в том, как реализовать слияние элемент за элементом.Я не знаю, как эти файлы можно контролировать для обработки одного и того же элемента.Используя условный сигнал?fork () или что-н.еще?Может кто-нибудь привести мне пример, потому что я не знаком ни с одним из способов.Thx.

вот пример объединения данных: file1:

<class name="math">

<string> luke1 </string>

<string> luke2 </string>

</class name>

<class name="music">

<string> mary1 </string>

<string> mary2 </string>

</class name>

file2:

<class name="math">

<string> luke1 </string>

<string> luke3 </string>

</class name>

<class name="music">

<string> mary1 </string>

<string> mary3 </string>

</class name>

<class name="english">

<string> tom1 </string>

<string> tom2 </string>

</class name>

должны быть объединены в другой файл как:

<class name="math">

<string> luke1 </string>

<string> luke2 </string>

<string> luke3 </string>

</class name>

<class name="music">

<string> mary1 </string>

<string> mary2 </string>

<string> mary3 </string>

</class name>

<class name="english">

<string> tom1 </string>

<string> том2</string>

</class name>

Примечание. Я хочу объединить элемент math всех файлов, затем объединить элемент музыки всех файлов, а затем объединить элемент english всех файлов.

Ответы [ 3 ]

2 голосов
/ 23 июля 2010

UPDATE:

Да, вы можете попытаться обработать 3 файла «параллельно», используя SAX-парсеры, если ваши обратные вызовы реализуют механизм «Сон / пробуждение / проверка, если другие SAX-парсеры сказали, что продолжают». В основном плохое приближение потоков и обмена сообщениями.

Это сработало бы только в том случае, если элементы в каждом XML-файле были упорядочены в одном и том же точном порядке и, в идеале, в алфавитном порядке - таким образом, вы можете перемещаться линейно внутри каждого файла с помощью SAX-анализатора и гарантировать, что вы попадете в идентичные элементы одновременно и, таким образом, одновременно хранит только 3-6 элементов в памяти. В основном это объединение 3 отсортированных массивов в 1 отсортированный массив.

Я серьезно сомневаюсь, что этот подход даже отдаленно превзошел бы исходный алгоритм, который я перечислил ниже, но если это то, что вы хотите попробовать реализовать, сделайте это.

ОРИГИНАЛ:

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

Вероятно, отображение имени элемента или идентификатора элемента в N полей true / false, по одному для каждого файла XML; или даже одно значение «да / нет» для «уже объединено» - я буду использовать последний вариант в моем примере логики ниже.

Будет ли эта база данных реализована как хэш в памяти; или связанный хеш, сохраненный в файле, чтобы избежать проблем с памятью, или правильная база данных (реализованная как XML, или как SQLite, или DBM, или реальный сервер базы данных) менее важна; за исключением того, что первый вариант явно отстой в потреблении памяти.

Обратите внимание на опцию базы данных XML, поскольку вы МОЖЕТЕ использовать полученный XML-файл в качестве базы данных. На самом деле это может быть вашим самым простым вариантом, не уверен - я бы лично порекомендовал связанный хеш или реальный сервер базы данных, если он у вас есть.

Сделав это, алгоритм очевиден:

  • Зацикливание каждого файла с использованием SAX-парсера

  • По каждому найденному элементу найдите этот элемент в базе данных. если уже помечено как обработанное, пропустите. Если нет, добавить в базу данных как обработано.

  • Найдите этот же элемент во всех последующих файлах, используя XPath. Например. при обработке file2.xml ищите только file3.xml, поскольку file1.xml не имел бы элемента (иначе он был бы обработан из file1.xml и уже появился в базе данных).

  • Объедините все элементы, которые вы нашли с помощью XPath, а также элемент из текущего файла, вставьте в результирующий файл XML и сохраните его.

  • Конец обеих петель.

Обратите внимание, что в этом ответе не указывается напрямую, какие модули использовать для реализации каждого шага - предположительно, XML :: Parser или любой другой синтаксический анализатор sax для синтаксического анализа, XML :: XPath для поиска в других файлах и что-то вроде XML :: Я предполагаю, что SAX :: Writer для записи результирующего файла, хотя, поскольку мне никогда не приходилось писать файл в модели, отличной от DOM, я не хочу делать последние официальной рекомендацией; и если вы хотите узнать, какой модуль лучше для этого, вы можете сделать это отдельным вопросом или надеяться, что кто-то другой ответит на этот вопрос с более точными рекомендациями модуля.

0 голосов
/ 23 июля 2010

Мне нравится XML :: LibXML, поэтому я бы использовал XML :: LibXML :: Reader. Откройте отдельный XML :: LibXML :: Reader для каждого входного файла, указанного в качестве аргумента для вашего скрипта, и просто вызовите -> прочитайте каждый из них по очереди, воспроизводя входные данные на выходе только один раз для каждого раунда, с немного более сложным логика в точках слияния. Если у вас больше входных файлов, чем файловых дескрипторов, вам придется объединять их в пакеты; Я бы сделал это в сценарии оболочки или Makefile.

0 голосов
/ 23 июля 2010

(извините, я не мог как-то добавить комментарий, поэтому я должен опубликовать свой комментарий в "опубликовать свой ответ")

Привет DVK,

Я не понимаю, что вы имеете в виду.Как я уже сказал, я не хочу разбирать файл за файлом, т.е.проанализировать все элементы в file1, записать данные в памяти, затем проанализировать все элементы в file2, записать данные в памяти и объединить их с данными, полученными из file1, затем проанализировать все элементы в file3 .... и, наконец, получить объединенные данныеи сохраните его в файле результатов.такой подход кушает много памяти.

поэтому я хочу обработать один элемент всех файлов, сохранить его, освободить память этого элемента, затем обработать следующий элемент всех файлов, сохранить его ....

Я не понимаючто такое Loop над каждым файлом.так что вы все еще предлагаете использовать первый подход, который я упомянул?что такое «Найти тот же элемент во всех последующих файлах», вы анализируете все файлы, теперь вы хотите снова проанализировать каждый элемент каждого файла, используя XPATH?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...