gpt4 book ai didi

xml - 使用 xml-conduit 的脆弱和冗长的代码

转载 作者:数据小太阳 更新时间:2023-10-29 02:11:16 27 4
gpt4 key购买 nike

我使用 XML-conduit 构建了一个 GPX 解析器并且在识别元素和跳过不需要的标签时遇到了过于冗长和脆弱的代码问题。

识别元素(一个小麻烦)

我通过仅比较 nameLocalName 来明确忽略 namespace 。我想正确的方法是将正确的命名空间硬编码到程序中,并让助手构造我的元素名称以便在 tag* 函数中进行比较?这有点烦人,因为我必须支持至少两个不同的 namespace (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* 变体可以为我做这件事(在没有所有 child 被消耗的情况下成功)但是没有这个事实表明我缺少一个简单的组合器或者应该发送补丁 - 这是什么?

最佳答案

如果您根本不使用命名空间,使用 Data.Conduit.List.map stripNamespace 之类的东西将它们完全剥离可能是最简单的。

坦率地说,我并没有真正使用自己经常使用的流媒体界面;我几乎所有的工作都涉及 DOM (Text.XML) 或游标界面。所以完全有可能缺少组合器。但在这种情况下,我相信您可以大大简化实现,因为 tagPredicate 不应允许内部 Sink 读取元素末尾之后的内容。所以你可以重写 skipTagAndContents 为:

tagPredicate ((== n) . nameLocalName) ignoreAttrs (const Data.Conduit.List.sinkNull)

你应该在把它放进去之前测试一下,我可能会错误地记住流接口(interface)的一些细节。

关于xml - 使用 xml-conduit 的脆弱和冗长的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10875179/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com