私はXML コンジットを使用して GPX パーサーを構築しましたが、要素を識別して不要なタグをスキップするための過度に冗長で脆弱なコードに問題がありました。
要素の識別 (マイナーな煩わしさ)
sのみを比較して、名前空間を明示的に無視していnameLocalName
ます。tag*
正しい名前空間をプログラムにハードコードし、関数で比較するためにヘルパーに要素名を作成させるのが正しい方法だと思いますか? これは、少なくとも 2 つの異なる名前空間 (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*
です(すべての子が消費されることなく成功します)が、単純なコンビネーターが不足しているか、パッチを送信する必要があることを示唆していないという事実はありますか?