Как объединить результаты запросов zip-фильтра в дереве XML в Clojure?
-
20-09-2019 - |
Вопрос
Я хочу объединить результаты трех запросов zip-фильтра в дереве XML.XML, который я анализирую, выглядит следующим образом:
<someroot>
<publication>
<contributors>
<person_name>
<surname>Surname A</surname>
</person_name>
<person_name>
<given_name>Given B</given_name>
<surname>Surname B</surname>
<suffix>Suffix B</suffix>
</person_name>
</contributors>
</publication>
</someroot>
Из этого примера вы можете видеть, что <given_name>
и <suffix>
являются необязательными - только <surname>
требуется.Здесь и заключается моя проблема: если я запущу три отдельных запроса, ответы, которые я получу, будут не в порядке друг с другом:
(xml-> xml :publication :contributors :person_name :given_name text)
(xml-> xml :publication :contributors :person_name :surname text)
(xml-> xml :publication :contributors :person_name :suffix text)
После выполнения этих трех запросов у меня останутся три последовательности, мощности которых не совпадают; given_name
и suffix
будет длина 1, в то время как surname
будет длина 2.Это лишает меня возможности объединить компоненты каждого имени.Мне нужно написать один запрос, который будет выполнять объединение имен во время построения последовательности.
Я просматриваю очень скудную документацию для clojure.contrib.zip-filter.xml
и не могу понять, как я мог это сделать (и возможно ли это вообще).К сожалению, я новичок в Clojure (и Lisp)!Может ли кто-нибудь указать, как я могу написать запрос, который объединит три других встроенных запроса?
Решение
Вы можете получить все поддеревья людей за один шаг (xml-> xmlzip :publication :contributors :person_name), затем получить части имени, если они существуют (xml1->personzip :surname text), и объединить их для получения желаемого результата следующим образом:
(use 'clojure.contrib.zip-filter.xml)
(defn format-name
[surname given suffix]
(str surname (if given (str ", " given)) (if suffix (str ", " suffix))))
(defn get-names
[xz]
(map (juxt
#(xml1-> % :surname text)
#(xml1-> % :given_name text)
#(xml1-> % :suffix text))
(xml-> xz :publication :contributors :person_name)))
(let [x (clojure.zip/xml-zip (clojure.xml/parse "foo.xml"))]
(map (partial apply format-name) (get-names x)))
Результат: («Фамилия А», «Фамилия Б, имя Б, суффикс Б»)
Другие советы
Я предполагаю, что альтернативное решение состоит в том, чтобы
(xml-> xml :publication :contributors :person_name)
а затем обработать каждый <person_name>
позже.