HXT:如何“提升”children某些元素?
HXT: how to “lift” children of certain elements?
假设我有这个 MathML 文档
<?xml version="1.0" encoding="UTF-8”?>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi> f </mi>
<mo> ⁡ </mo>
<mrow>
<mo> ( </mo>
<mi> x </mi>
<mo> ) </mo>
</mrow>
</math>
假设我想“提升”mi
和mrow
的children,我应该得到(让我们忽略这里的空白变化)
<?xml version="1.0" encoding="UTF-8"?>
<math xmlns="http://www.w3.org/1998/Math/MathML">
f
<mo> ⁡ </mo>
<mo> ( </mo>
x
<mo> ) </mo>
</math>
HXT应该怎么写?
我是 Haskell 新手...所以我现在只有
-- Dealing with command line arguments and stuff…
processRootElement :: IOSArrow XmlTree XmlTree
processRootElement
= processTopDown -- What goes here?
快速输入摘要
XmlTree = NTree XNode
意思是每个XmlTree
都有结构
NTree XNode [XMLTree]
其中第一个参数是当前节点,第二个参数是children的列表。
创作过程
processTopDown
将采用您提供的树转换并生成递归应用它的树转换。
首先,让我们在单个节点上定义您想要的树转换:
- 遍历当前节点children
- 如果有匹配我们指定的标签,那么
- 取标签的所有children,
- 使它们成为当前节点的 children
- 然后删除标签
转换不会 "lift" 当前节点的 children,因为这在根节点上是不可能的。
一个好的方法是使用 processChildren
,这是一个箭头,它让我们根据旧的 children 为当前节点指定新的 children。为此,我们需要使用 conditional arrows
然后我们可以将设计分成两部分,用于匹配我们想要的标签的谓词,以及我们想要执行的转换
谓词
提醒自己 what forms 一个 XNode
可以拿,我们感兴趣的是
XTag QName XmlTrees
我们希望在这种形式的节点上匹配给定的标签名称。为此,我们编写了一个辅助函数
filterOnQName :: QName -> XNode -> Bool
filterOnQName qname (XTag xqname _)
| qname == xqname = True
| otherwise = False
filterOnQName _ _ = False
为了方便使用,我们希望将标签写成字符串,所以我们将使用mkName
将它们转换为QName
。那么我们比较有用的过滤函数是
filterTags :: [String] -> XmlTree -> Bool
filterTags tagNames (NTree xnode _) = any (\qname -> filterOnQName qname xnode) (map mkName tagNames)
但这不是箭头,我们需要它是出于稍后会看到的原因。我们可以简单地将它变成一个 isA
childFilter tags = isA (filterTags tags)
转型
我们要两个,转换主体需要两个箭头 - 一个用于过滤器匹配时,一个用于过滤器不匹配时。
如果没有,转换很容易 - 我们想保留当前节点。
filterFailed = this
在这里,this
是标识箭头 - 它什么都不做。
当过滤器匹配时,我们想要得到 children - 首先,让我们写一个帮助程序
getChildren :: XmlTree -> [XmlTree]
getChildren (NTree _ children) = children
方便地,因为我们正在使用列表箭头,我们可以使用 arrL
将其直接变成箭头
liftChildren = arrL getChildren
合并它们
我们现在可以使用 ifA
将其变成单个箭头,if
的箭头版本
liftMatchedChildren tags = ifA (childFilter tags) liftChildren filterFailed
最后,我们可以描述我们想要的转换
processRootElement
= processTopDown (processChildren (liftMatchedChildren ["mi", "mrow"]))
假设我有这个 MathML 文档
<?xml version="1.0" encoding="UTF-8”?>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi> f </mi>
<mo> ⁡ </mo>
<mrow>
<mo> ( </mo>
<mi> x </mi>
<mo> ) </mo>
</mrow>
</math>
假设我想“提升”mi
和mrow
的children,我应该得到(让我们忽略这里的空白变化)
<?xml version="1.0" encoding="UTF-8"?>
<math xmlns="http://www.w3.org/1998/Math/MathML">
f
<mo> ⁡ </mo>
<mo> ( </mo>
x
<mo> ) </mo>
</math>
HXT应该怎么写?
我是 Haskell 新手...所以我现在只有
-- Dealing with command line arguments and stuff…
processRootElement :: IOSArrow XmlTree XmlTree
processRootElement
= processTopDown -- What goes here?
快速输入摘要
XmlTree = NTree XNode
意思是每个XmlTree
都有结构
NTree XNode [XMLTree]
其中第一个参数是当前节点,第二个参数是children的列表。
创作过程
processTopDown
将采用您提供的树转换并生成递归应用它的树转换。
首先,让我们在单个节点上定义您想要的树转换:
- 遍历当前节点children
- 如果有匹配我们指定的标签,那么
- 取标签的所有children,
- 使它们成为当前节点的 children
- 然后删除标签
转换不会 "lift" 当前节点的 children,因为这在根节点上是不可能的。
一个好的方法是使用 processChildren
,这是一个箭头,它让我们根据旧的 children 为当前节点指定新的 children。为此,我们需要使用 conditional arrows
然后我们可以将设计分成两部分,用于匹配我们想要的标签的谓词,以及我们想要执行的转换
谓词
提醒自己 what forms 一个 XNode
可以拿,我们感兴趣的是
XTag QName XmlTrees
我们希望在这种形式的节点上匹配给定的标签名称。为此,我们编写了一个辅助函数
filterOnQName :: QName -> XNode -> Bool
filterOnQName qname (XTag xqname _)
| qname == xqname = True
| otherwise = False
filterOnQName _ _ = False
为了方便使用,我们希望将标签写成字符串,所以我们将使用mkName
将它们转换为QName
。那么我们比较有用的过滤函数是
filterTags :: [String] -> XmlTree -> Bool
filterTags tagNames (NTree xnode _) = any (\qname -> filterOnQName qname xnode) (map mkName tagNames)
但这不是箭头,我们需要它是出于稍后会看到的原因。我们可以简单地将它变成一个 isA
childFilter tags = isA (filterTags tags)
转型
我们要两个,转换主体需要两个箭头 - 一个用于过滤器匹配时,一个用于过滤器不匹配时。
如果没有,转换很容易 - 我们想保留当前节点。
filterFailed = this
在这里,this
是标识箭头 - 它什么都不做。
当过滤器匹配时,我们想要得到 children - 首先,让我们写一个帮助程序
getChildren :: XmlTree -> [XmlTree]
getChildren (NTree _ children) = children
方便地,因为我们正在使用列表箭头,我们可以使用 arrL
将其直接变成箭头liftChildren = arrL getChildren
合并它们
我们现在可以使用 ifA
将其变成单个箭头,if
liftMatchedChildren tags = ifA (childFilter tags) liftChildren filterFailed
最后,我们可以描述我们想要的转换
processRootElement
= processTopDown (processChildren (liftMatchedChildren ["mi", "mrow"]))