0

我目前正在从事一个项目,我将文本挖掘应用于大量 xml 文件。我使用 xml2 包来处理 xml 和 stringr 包来处理大多数文本挖掘任务。

我遇到了一个奇怪的问题。一些 xml 文档包含搞砸功能的奇怪空格字符,因此我需要先将这些空格字符替换为普通空格字符。为此,我将 xml 文档中的所有节点分开,提取文本,更改它,然后将更改后的字符串分配回节点,如下所示:xml_text(node) <- str_replace_all(xml_text(node), "[:space:]", " "),这在更改空格字符方面是成功的。这是我的代码的简化版本:

# required libraries
require(xml2)
require(stringr)

testfunctie <- function(xmlstring)
{
  # turn string into xml nodeset
  data<-read_xml(xmlstring)
  # take every node separately
  data<-xml_find_all(data, "//*")
  browser()
  # replace weird space characters by regular ones
  for (i in 1:length(data))
  {
    xml_text(data[[i]]) <- str_replace_all(xml_text(data[[i]]), "[:space:]", " ")
  }
  # find all nodes containing a certain text
  tree <- xml_find_all(data, "//dossiernr[text()='ExampleText']")
  browser()
  return(tree)
}

# XML example
exampleXML<-"<dossier>
<dossiernummer>
<dossiernr>ExampleText</dossiernr>
</dossiernummer>
<titel>AnotherPieceOfExampleText</titel>
</dossier>"

mvt <- testfunctie(exampleXML)

通常这可以正常工作,但在某些情况下会出现奇怪的问题,并且通过 xml_text() 提取的文本也包含来自其他节点的文本。您可以通过运行上面的代码看到这一点。当第一个 browser() 语句触发时,选择剩余的代码直到第二个 browser() 语句(第 13-18 行)并手动运行它。对象“tree”将是一个长度为 1 的列表,因为 xml_find_all() 函数找到了名为“dossiernr”的节点(节点集“data”中的第三个节点),因为该节点内的文本是“ExampleText” . 您可以通过在控制台中输入来验证这一点xml_text(data[[3]]),它等于xml_text(tree[[1]]). 这就是它应该如何工作的方式。

但是,如果您在第一个浏览器语句之后单击“继续”并自动运行其余代码,当您到达第二个浏览器语句时,“树”将是一个长度为 0 的列表。如果您然后键入xml_text(data[[3]]),结果是节点内的文本已替换为“ExampleTextAnotherPieceOfExampleText”,而不仅仅是“ExampleText”。另一个节点(名为“titel”的节点)内的文本被附加到它。

因此,出于某种原因,此代码的行为会有所不同,具体取决于我是手动运行还是自动运行。谁能帮我理解为什么会发生这种情况,以及如何解决这种行为?提前致谢。

4

1 回答 1

0

xml_text 函数返回父节点和所有叶节点中的所有文本,这就是为什么某些节点是合并值的原因。这似乎是不一致的行为。

我的建议不是尝试在每个节点上操作并替换文本,而是使用 str_replace_all 对整个 xml 文档执行全局替换,然后将数据重新读取为 xml。

# XML example
exampleXML<-"<dossier>
<dossiernummer>
<dossiernr>ExampleText</dossiernr>
</dossiernummer>
<titel>AnotherPieceOfExampleText</titel>
</dossier>"

data<-read_xml(exampleXML)

data<-str_replace_all(data, "[:space:]", " ")

data<-read_xml(data)
于 2018-03-15T13:24:40.873 回答