我使用XML-conduit構建了一個GPX分析器,並且存在用於標識元素和跳過不需要的標記的過於冗長和易碎代碼的問題。使用xml導管的易碎和冗長的代碼
識別元素(一個小麻煩)
我明確地只比較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*
變體會爲我做到這一點(成功沒有所有的孩子被消費),但事實是,沒有暗示我錯過了一個簡單的combinator或應該發送補丁 - 這是什麼?
我有類似的代碼,它會導致錯誤,如'XmlException {xmlErrorMessage ='期望的結束標記爲:名稱{nameLocalName = \「metadata \」,nameNamespace = Just \「http://www.topografix.com/ GPX/1/1 \「,namePrefix = Nothing}」,xmlBadInput = Nothing}'。所以現在我會堅持我的實現,明確表示結束標記。 stripNamespace會清理一些東西 - 謝謝! –