Я построил парсер GPX с использованием XML-conduit и имел проблемы с чрезмерно подробным и хрупким кодом для идентификации элементов и пропуска нежелательных тегов.Хрупкий и подробный код с использованием xml-conduit
Определение элементов (незначительное раздражение)
Я явно пренебрегая пространство имен путем сравнения только nameLocalName
сек. Я предполагаю, что правильным способом является жесткое кодирование правильного пространства имен в программе и наличие вспомогательных конструкций для моих имен элементов для сравнения в функциях tag*
? Это немного раздражает, так как я должен поддерживать по крайней мере два разных пространства имен (GPX 1.1 и 1.0), которые достаточно схожи, что они не требуют изменений кода для моих целей.
Досрочных элементы
GPX является великоватым и множество пользовательских расширений больше. Поскольку инструмент, который я создаю, нуждается в ограниченной информации, я решил игнорировать определенные теги вместе со всеми их подэлементами. Например:
<trkpnt lat="45.19843" lon="-122.428">
<ele>4</ele>
<time>...</time>
<extensions>
...
</extensions>
</trkpnt>
Игнорирования extensions
и подобные метки с многочисленными субэлементами я сделал мойку, что бы потребить элементы до конца элемента Event
:
skipTagAndContents :: (MonadThrow m) => Text -> Sink Event m (Maybe())
skipTagAndContents n = tagPredicate ((== n) . nameLocalName)
ignoreAttrs
(const $ many (skipElements n) >> return())
skipElements t = do
x <- await
case x of
Just (EventEndElement n) | nameLocalName n == t -> Done x Nothing
Nothing -> Done x Nothing
_ -> return (Just())
Кажется, там должна быть tag*
вариант, сделаю это для меня (преуспеть, если не будут поглощены все дети), но тот факт, что я не предлагаю, чтобы я пропустил простой комбинатор или должен отправить патч - что это?
У меня был аналогичный код, и он приводит к ошибкам, таким как 'XmlException {xmlErrorMessage =" Ожидаемый конечный тег для: Name {nameLocalName = \ "metadata \", nameNamespace = Just \ "http://www.topografix.com/ GPX/1/1 \ ", namePrefix = Nothing}", xmlBadInput = Nothing} '. Поэтому на данный момент я буду придерживаться своей реализации, в которой явно указано конечный тег. ПолосаNamespace очистит что-то, хотя - спасибо! –