我目前正在从事一个项目,我将文本挖掘应用于大量 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”的节点)内的文本被附加到它。
因此,出于某种原因,此代码的行为会有所不同,具体取决于我是手动运行还是自动运行。谁能帮我理解为什么会发生这种情况,以及如何解决这种行为?提前致谢。