如何替换R中XML元素内的文本?

Man*_*ish 5 xml replace r

我有一个输入xml文件.

cat sample.xml

<Text>
    &lt;p&gt;ABC &lt;/p&gt;
</Text>
Run Code Online (Sandbox Code Playgroud)

R脚本

library(XML)
doc = xmlTreeParse("sample.xml", useInternal = TRUE)
top<-xmlRoot(doc)

sub("&lt;","<",top[[1]])
Run Code Online (Sandbox Code Playgroud)

我怎样才能修复上面的pblm?

错误消息:as.vector(x,"character")中的错误:无法强制将'externalptr'类型强制转换为'character'类型的向量

编辑:目标是对xml中的特定节点使用readHTMLTable()函数,该函数具有html表但是它具有xml标记(&gt;&lt;)for>和<需要首先重新执行,因为readHTMLTable函数无法处理xml标记.

Spa*_*man 7

现在回答你真正的问题:

带编码表的sample.xml:

<Text>
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;32&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
</Text>
Run Code Online (Sandbox Code Playgroud)

阅读:

> library(XML)
> doc = xmlTreeParse("sample.xml", useInternal = TRUE)
> top<-xmlRoot(doc)
Run Code Online (Sandbox Code Playgroud)

转换为文字:

> table=xmlValue(top)
> table
[1] "\n<table>\n<tr><td>1</td><td>2</td></tr>\n<tr><td>2</td><td>8</td></tr>\n<tr><td>4</td><td>32</td></tr>\n</table>\n"
Run Code Online (Sandbox Code Playgroud)

现在已经准备好了readHTMLTable.无需字符串转换:

> readHTMLTable(table)
$`NULL`
  V1 V2
1  1  2
2  2  8
3  4 32
Run Code Online (Sandbox Code Playgroud)

Howzat?


jub*_*uba 5

如果您的问题是要知道如何替换XML节点内容中的字符串,那么您可以使用sample.xml您提供的文件检查以下代码:

## Parse the XML file
doc <- xmlTreeParse("sample.xml", useInternal = TRUE)
## Select the nodes we want to update
nodes <- getNodeSet(doc, "//Text")
## For each node, apply gsub on the content of the node
lapply(nodes, function(n) {
  xmlValue(n) <- gsub("ABC","foobar",xmlValue(n))
})
Run Code Online (Sandbox Code Playgroud)

哪个会给你:

R> doc
<?xml version="1.0"?>
<Text>
    &lt;p&gt;foobar &lt;/p&gt;
</Text>
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到"ABC"被"foobar"取代.

但是,如果你尝试使用你想要实现的替换代码(替换"<"wit"<"),它显然不会起作用:

doc <- xmlTreeParse("sample.xml", useInternal = TRUE)
nodes <- getNodeSet(doc, "//Text")
lapply(nodes, function(n) {
  xmlValue(n) <- gsub("&lt;","<",xmlValue(n))
})
Run Code Online (Sandbox Code Playgroud)

会给你 :

R> doc
<?xml version="1.0"?>
<Text>
    &lt;p&gt;ABC &lt;/p&gt;
</Text>
Run Code Online (Sandbox Code Playgroud)

为什么?如果您正在处理XML文件,您应该知道某些字符,主要是<,>,&和"是保留的,因为它们是基本XML语法的一部分.因此,它们不能出现在节点的内容中,否则会解析因此它们被实体取代,实体是这些字符的一种编码.例如,"<"编码为"<","&"编码为"&"等.

所以在这里,节点的内容包含一个"<"字符,该字符已自动转换为他的实体"<".您尝试对代码执行的操作是替换"<" 回到"<",R很乐意为你做,但由于它是节点的文本内容,XML包将立即将其转换回"<".

所以,如果你想要实现的是转换你的字符串"< p> ABC</p>" 到新的XML节点"<p> ABC </ p>",你不能这样做.一个解决方案是解析你的文本字符串,从中检测名称和节点(这里是"p"),创建一个新节点xmlNode(),给它文本内容"ABC"并用你刚才的节点替换字符串创建.

另一种快速而又脏的方法是首先替换文件中的所有实体而不解析XML.像这样的东西:

txt <- readLines(file("sample.xml"))
txt <- gsub("&lt;", "<", txt)
txt <- gsub("&gt;", ">", txt)
writeLines(txt, file("sample2.xml"))
doc2 <- xmlTreeParse("sample2.xml", useInternal = TRUE)
Run Code Online (Sandbox Code Playgroud)

这使 :

R> doc2
<?xml version="1.0"?>
<Text>
  <p>ABC </p>
</Text>
Run Code Online (Sandbox Code Playgroud)

但这很危险,因为如果有一个"真实的""<" 您文件中的实体,解析将失败.