当前位置 : 主页 > 网页制作 > xml >

R:将节点插入特定位置的xml树中

来源:互联网 收集:自由互联 发布时间:2021-06-13
数据 我有一个像这样的结构的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" des
数据

我有一个像这样的结构的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>

具体而言,任何标记节点的大小都是未知的,所有标记节点的属性数量不相等,并且属性的值不是唯一的.
然而,我所知道的是searchA属性的值是唯一的.此外,只有标记节点可以包含一个名为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()的节点.
即使我以某种方式设法将indexVector和所有节点的xmlSize()映射到我可以直接在xmltop上使用的正确索引,我仍然会遇到可变数量的双括号问题(xmltop [[1]] [ [3]] vs xmltop [[1]] [[2]] [[1]]).

我还尝试了XML包的其他几个函数,包括xmlApply,getNodeLocation和getNodeSet,但它们似乎没有帮助.

我没有真正尝试过的

我真的不明白xmlTreeParse(),xmlInternalTreeParse()和xmlTreeParse(useInternalNodes = T)的区别,我不能把我的脑袋包裹在XPath中,所以我没有尝试使用它.

任何有用的指针将非常感激.

我混淆的原因是?xmlElementsByTagName的帮助页面.它说:

“The addition of the recursive argument makes this function behave like the getElementsByTagName in other language APIs such as Java, C\#. However, one should be careful to understand that in those languages, one would get back a set of node objects. These nodes have references to their parents and children. Therefore one can navigate the tree from each node, find its relations, etc. In the current version of this package (and for the forseeable future), the node set is a “copy” of the nodes in the original tree. And these have no facilities for finding their siblings or parent.”

这让我觉得该函数返回一个副本列表而不是对节点本身的引用.
如果使用设置为FALSE的xmlTreeParse()函数的标志useInternalNodes解析xml,可能就是这种情况,但如果在解析时将其设置为TRUE,则xmlElementsByTagName()返回的列表似乎包含实际引用.
这些可以使用例如addChildren()轻松操作.

简而言之,我的问题的简单解决方案是:

addChildren(listOfNodes[indexVector], kids = list(newNode))
网友评论