哪个XPath可以识别具有共同兄弟的节点?

时间:2015-07-03 15:59:43

标签: xml r xpath

我有一个看起来像这样的xml文件(使用R来解析代码):

code <- '<a>

  <b>
    <c>1</c>
    <c>2</c>
  </b>

  <b>
    <c>3</c>
    <c>4</c>
  </b>

  <c>5</c>
  <c>6</c>

  <b>
    <c>7</c>
    <c>8</c>
  </b>

  <c>9</c>
  <c>10</c>

</a>'

library(XML)
parsed <- xmlParse(code)

我正在处理的问题是该文件因我需要的目的而部分格式错误。正确的格式要求每个c节点必须嵌套在b标签中。正如您所看到的那样,某些节点是正确的,但对于值为5,6,9,10的c节点则不然。

我知道如何使用XML包处理和编辑XML节点。我现在面临的问题是我需要单独解决两组c节点,即我需要提出一个XPath表达式,将c节点(5,6)识别为一组c节点(9,10) )作为另一组。一个简单的&#34; // c&#34;只识别不是我想要的所有c节点。

解决方案

我以为我分享了我提出的解决方案。它从chorobas XPath开始,然后将兄弟链连接到此节点,检查它们的名称并重复此过程,直到它到达b节点。也许这有助于某人。

  node1 <- XML::getNodeSet(parsed, "/a/c[preceding-sibling::*[1]/self::b]")

  if(length(node1) > 0){

    for(i in 1:length(node1)){

      node.container <- list()
      node.container[[1]] <- node1[[i]]

      gg <- 1
      repeat{
        sibling.node <- XML::getSibling(node.container[[gg]])

        if(is.null(sibling.node)) break
        if(!(XML::xmlName(sibling.node) == "c"))) break

        node.container[[gg + 1]] <- sibling.node
        gg <- gg + 1
      }

      invisible(new.b <- XML::newXMLNode("b"))
      invisible(XML::replaceNodes(oldNode = node1[[i]], newNode = new.b))
      invisible(XML::addChildren(new.b, node.container))
    }

  }

2 个答案:

答案 0 :(得分:1)

XPath无法返回节点组,它会返回一个节点列表。你可以轻松地让它返回对中的第一个:

/a/c[preceding-sibling::*[1]/self::b]

(即c下的a,其前一个兄弟是b),

或者,如果结构在某个更深的地方

//c[parent::a][preceding-sibling::*[1]/self::b]

要进入第二个节点,只需使用following-sibling::c[1]

注意:  在c的最开始,这不会抓住a对。

答案 1 :(得分:0)

您可以使用

找到c不是b子节点的所有getNodeSet(parsed, "//c[name(parent::*)!='b']") 个节点
c

如果你想要那些后跟badc <- getNodeSet(parsed, "//c[name(parent::*)!='b' and name(following-sibling::*)='c']") (一对的开头)的人。你可以做到。

xmlApply(badc, xpathSApply, "./following-sibling::c[1]")

你可以通过

获得下一对
Object.observe