我有一个输入xml文件。
cat sample.xml
<Text>
<p>ABC </p>
</Text>
R脚本
library(XML)
doc = xmlTreeParse("sample.xml", useInternal = TRUE)
top<-xmlRoot(doc)
sub("<","<",top[[1]])
我如何解决上面的pblm?
错误消息:as.vector(x,“character”)出错: 不能强迫'externalptr'类型为'character'类型的向量
编辑:目的是对xml中的特定节点使用readHTMLTable()函数,该节点具有html表但是对于&gt;它具有xml标记(>
和<
)。和&lt;首先需要重新定位,因为readHTMLTable函数无法处理xml标记。
答案 0 :(得分:6)
现在回答你真正的问题:
包含编码表的sample.xml:
<Text>
<table>
<tr><td>1</td><td>2</td></tr>
<tr><td>2</td><td>8</td></tr>
<tr><td>4</td><td>32</td></tr>
</table>
</Text>
阅读:
> library(XML)
> doc = xmlTreeParse("sample.xml", useInternal = TRUE)
> top<-xmlRoot(doc)
转换为文字:
> 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"
现已准备好向readHTMLTable
提供信息。无需字符串转换:
> readHTMLTable(table)
$`NULL`
V1 V2
1 1 2
2 2 8
3 4 32
Howzat?
答案 1 :(得分: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))
})
哪个会给你:
R> doc
<?xml version="1.0"?>
<Text>
<p>foobar </p>
</Text>
在这里你可以看到“ABC”被“foobar”取代。
但是,如果你尝试使用你想要实现的替换代码(替换“&amp; lt;”wit“&lt;”),它显然不起作用:
doc <- xmlTreeParse("sample.xml", useInternal = TRUE)
nodes <- getNodeSet(doc, "//Text")
lapply(nodes, function(n) {
xmlValue(n) <- gsub("<","<",xmlValue(n))
})
会给你:
R> doc
<?xml version="1.0"?>
<Text>
<p>ABC </p>
</Text>
为什么?如果你正在使用XML文件,你应该知道一些字符,主要是&lt;,&gt;,&amp;并且“保留,因为它们是基本XML语法的一部分。因此,它们不能出现在节点的内容中,否则解析将失败。因此它们被实体取代,这是一种排序例如,“&lt;”编码为“&amp; lt;”,“&amp;”编码为“&amp; amp;”等。
所以在这里,节点的内容包含“&lt;”字符,已自动转换为他的实体“&amp; lt;”。您尝试对代码执行的操作是替换“&amp; lt;”回到“&lt;”,R很乐意为你做,但由于它是节点的文本内容,XML包将立即将其转换回“&amp; lt;”。
所以,如果你想要实现的是转换你的字符串“&amp; lt; p&amp; gt; ABC&amp; lt; / p&amp; gt;”对于新的XML节点“&lt; p&gt; ABC&lt; / p&gt;”,你不能这样做。解决方案是解析文本字符串,从中检测名称和节点(此处为“p”),使用xmlNode()
创建新节点,为其指定文本内容“ABC”并替换字符串使用您刚刚创建的节点。
另一种快速而又脏的方法是首先替换文件中的所有实体而不解析XML。像这样:
txt <- readLines(file("sample.xml"))
txt <- gsub("<", "<", txt)
txt <- gsub(">", ">", txt)
writeLines(txt, file("sample2.xml"))
doc2 <- xmlTreeParse("sample2.xml", useInternal = TRUE)
给出了:
R> doc2
<?xml version="1.0"?>
<Text>
<p>ABC </p>
</Text>
但这很危险,因为如果有“真实”“&amp; lt;”您文件中的实体,解析将失败。
答案 2 :(得分:3)
Ge xmlValue
节点的值并替换。在这里,我将用DEF取代ABC:
> top<-xmlRoot(doc)
> top
<Text>
<p>ABC </p>
</Text>
> xmlValue(top)=sub("ABC","DEF",xmlValue(top))
> top
<Text>
<p>DEF </p>
</Text>
我之所以不尝试更换&lt;是因为这些字符序列在某些时候被XML代码解释了:
> substr(xmlValue(top),6,6)=="<"
[1] TRUE
虽然我已尝试使用xmlTreeParse
和其他XML包函数的一些选项,但我似乎无法阻止xmlValue
解释它们......