R:将节点插入到特定位置的xml树中
Posted
技术标签:
【中文标题】R:将节点插入到特定位置的xml树中【英文标题】:R: Insert node into xml tree at specific location 【发布时间】:2016-05-14 02:42:21 【问题描述】:数据
我有一个类似这样结构的 xml 文件(展示所需灵活性的大示例):
<rootnode sth="something" descr="ex">
<tag sth="sth1" descr="ex" anoAttr="sth2">
<tag sth="sth3" descr="ex2" searchA="sth4" anoAttr="sth5">
<tag sth="sth6" descr="ex3" oAttr="sth7" searchA="sth8" anoAttr="sth9">
<tag sth="sth10" descr="ex4" oAttr="sth11" searchA="sth12" anoAttr="sth13">
<someContent/>
</tag>
<someContent/>
</tag>
<tag sth="sth14" descr="ex5" oAttr="sth15" searchA="sth16" anoAttr="sth17">
<someContent/>
</tag>
<tag sth="sth1" descr="ex6" oAttr="sth15" searchA="sth18" anoAttr="sth17">
<someContent/>
</tag>
</tag>
<tag sth="sth10" descr="ex2" oAttr="sth19" searchA="sth20" anoAttr="sth9">
<someContent/>
</tag>
<tag sth="sth10" descr="ex7" searchA="sth21" anoAttr="sth13">
<tag sth="sth21" descr="ex8" oAttr="sth22" searchA="sth23" anoAttr="sth9">
<tag sth="sth23" descr="ex9" oAttr="sth22" searchA="sth24" anoAttr="sth5">
<someContent/>
</tag>
<someContent/>
</tag>
</tag>
</tag>
<otherNode>
<someNode/>
</otherNode>
</rootnode>
具体来说,任何tag
节点的大小是未知的,所有tag
节点的属性数量不相等,并且属性的值不是唯一的。
然而,我所知道的是searchA
属性的值是唯一的。此外,只有tag
节点可以包含一个名为searchA
的属性,并且除了***节点之外的所有节点都可以。
之前
我首先使用带有函数xmlTreeParse()
的XML
包解析此文档并存储根节点。然后我使用newXMLNode()
创建一个新节点。
xmlfile = xmlTreeParse(filename, useInternalNodes = TRUE)
xmltop = xmlRoot(xmlfile)
newNode = newXMLNode(name = "newlyCreatedNode")
目标
我的目标是将我新创建的newNode
作为具有特定值(例如"sth23"
)的节点的子节点插入searchA
属性。
所以在这种情况下,我希望结果看起来像这样(注意底部附近的<newlyCreatedNode/>
):
<rootnode sth="something" descr="ex">
<tag sth="sth1" descr="ex" anoAttr="sth2">
<tag sth="sth3" descr="ex2" searchA="sth4" anoAttr="sth5">
<tag sth="sth6" descr="ex3" oAttr="sth7" searchA="sth8" anoAttr="sth9">
<tag sth="sth10" descr="ex4" oAttr="sth11" searchA="sth12" anoAttr="sth13">
<someContent/>
</tag>
<someContent/>
</tag>
<tag sth="sth14" descr="ex5" oAttr="sth15" searchA="sth16" anoAttr="sth17">
<someContent/>
</tag>
<tag sth="sth1" descr="ex6" oAttr="sth15" searchA="sth18" anoAttr="sth17">
<someContent/>
</tag>
</tag>
<tag sth="sth10" descr="ex2" oAttr="sth19" searchA="sth20" anoAttr="sth9">
<someContent/>
</tag>
<tag sth="sth10" descr="ex7" searchA="sth21" anoAttr="sth13">
<tag sth="sth21" descr="ex8" oAttr="sth22" searchA="sth23" anoAttr="sth9">
<tag sth="sth23" descr="ex9" oAttr="sth22" searchA="sth24" anoAttr="sth5">
<someContent/>
</tag>
<someContent/>
<newlyCreatedNode/>
</tag>
</tag>
</tag>
<otherNode>
<someNode/>
</otherNode>
</rootnode>
基本上,在这种情况下,addChildren(xmltop[[1]][[3]][[1]], kids = list(newNode))
会得到我想要的结果。当然我不想指定[[1]][[3]][[1]]
。
我尝试了什么
我可以使用xmlElementsByTagName()
获取所有相关节点的列表,并使用xmlAttrs()
获取所有属性。我什至可以得到一个逻辑索引向量,它给了我正确的位置。
listOfNodes = xmlElementsByTagName(el = xmltop, "tag", recursive = T)
attributeList = lapply(listOfNodes, FUN = function(x) xmlAttrs(x))
indexVector = sapply(attributeList, FUN = function(x) x["searchA"] == "sth23")
indexVector[is.na(indexVector)] = FALSE
listOfNodes[indexVector]
我不知道如何使用这些信息将我的节点插入到树中的正确位置。listOfNodes[indexVector]
给了我正确的节点,但它现在是一个列表,而不是我可以的节点使用addChildren()
on。
即使我设法将所有节点的indexVector
和xmlSize()
映射到我可以直接在xmltop
上使用的正确索引,我仍然会遇到双括号数量可变的问题(xmltop[[1]][[3]]
与xmltop[[1]][[2]][[1]]
)。
我还尝试了XML
包的其他几个功能,包括xmlApply
、getNodeLocation
和getNodeSet
,但它们似乎没有帮助。
我没有真正尝试过的东西
我不太了解xmlTreeParse()
、xmlInternalTreeParse()
和xmlTreeParse(useInternalNodes = T)
的区别,而且我无法完全理解 XPath,所以我没有深入尝试使用它。
任何有用的指针将不胜感激。
【问题讨论】:
【参考方案1】:我感到困惑的原因是?xmlElementsByTagName
的帮助页面。上面写着:
“recursive 参数的添加使该函数的行为类似于 Java、C\# 等其他语言 API 中的 getElementsByTagName。但是,应该注意理解在那些语言中,人们会返回一组节点对象。这些节点具有对其父母和孩子的引用。因此,人们可以从每个节点导航树,找到它的关系等。在这个包的当前版本中(并且在可预见的未来),节点集是原始树中节点的“副本”。这些节点无法找到它们的兄弟姐妹或父节点。”
这让我觉得该函数返回一个副本列表,而不是对节点本身的引用。
如果在解析 xml 时将 xmlTreeParse()
函数的标志 useInternalNodes
设置为 FALSE
,则可能会出现这种情况,但如果在解析时将其设置为 TRUE
,则 xmlElementsByTagName()
返回的列表似乎包含实际参考。
这些可以很容易地使用例如addChildren()
进行操作。
简而言之,解决我的问题的非常简单的方法是:
addChildren(listOfNodes[indexVector], kids = list(newNode))
【讨论】:
以上是关于R:将节点插入到特定位置的xml树中的主要内容,如果未能解决你的问题,请参考以下文章