【问题标题】:How to replace the text inside an XML element in R?如何替换 R 中 XML 元素内的文本?
【发布时间】:2013-01-15 06:39:47
【问题描述】:

我有一个输入 xml 文件。

猫样本.xml

<Text>
    &lt;p&gt;ABC &lt;/p&gt;
</Text>

R 脚本

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

sub("&lt;","<",top[[1]])

我该如何解决 pblm 以上问题?

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

编辑:目的是对 xml 中的特定节点使用 readHTMLTable() 函数,该节点具有 html 表,但它具有用于 > 和 &gt; 和 &amp;lt;),因为 readHTMLTable 函数不能处理 xml 标记。

【问题讨论】:

  • XML 实体标记GETS 被XML 包函数所取代,正如我所解释的。 xmlValue 函数返回这个。将其输入readHTMLTable 并完成工作。

标签: xml r replace


【解决方案1】:

现在是您真正问题的答案:

带有编码表的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>

阅读:

> 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

怎么样?

【讨论】:

  • 完美答案!无论如何要替换html表新表。$NULLV1 V2 1 1 2 2 2 8 3 4 32
  • 嗯什么?你想用 R 的输出替换 元素吗?这值得作为另一个问题提出,并且可能已经回答了......
  • 是的,我也想这样做。我只想用 R 的输出替换 中的 Table。
  • 好的,你现在正在移动球门柱。 StackOverflow 最适合解决简单问题。这个问题/答案已经解决了一个问题 - 如何获取和操作 XML 中的文本。现在去问一个单独的问题中的下一步。
  • 实际上我的目的不是操纵,而只是打印 的内容,如在此处上传的 textuploader.com/?p=6&id=5ZoIe 除了

    标签中的 html 表格跨度>
【解决方案2】:

如果您的问题是要知道如何替换 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>
    &lt;p&gt;foobar &lt;/p&gt;
</Text>

在这里你可以看到“ABC”被“foobar”取代了。

但是,如果您尝试使用您想要实现的替代代码(将“<”替换为“

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

会给你:

R> doc
<?xml version="1.0"?>
<Text>
    &lt;p&gt;ABC &lt;/p&gt;
</Text>

为什么?如果您正在使用 XML 文件,您应该知道某些字符,主要是 、& 和 " 是保留的,因为它们是基本 XML 语法的一部分。因此,它们不能出现在节点的内容中,否则会解析会失败。所以它们被替换为entities,这是对这些字符的一种编码。例如,“

所以这里,你节点的内容中包含了一个“

所以,如果你想要实现的是转换你的字符串 "<p>ABC </p>"到一个新的 XML 节点“

ABC

”,你不能那样做。一个解决方案是解析您的文本字符串,从中检测节点的名称和(此处为“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)

这给出了:

R> doc2
<?xml version="1.0"?>
<Text>
  <p>ABC </p>
</Text>

但是这是危险的,因为如果有一个“真实的”“<”文件中的实体,解析将失败。

【讨论】:

  • 以上代码将 xml 节点转换为列表,但我需要 xml 输出,以便我可以使用 readHTMLTable() 函数来此节点。
  • 是的,我知道您需要 xml 输出,这就是我帖子的重点。以及将xml转换为列表的代码是什么?
  • 我已经编辑了我的问题。我无法将 readHTMLTable 函数与 xmlNode 一起使用。
  • 是的。而且您必须将您的字符串转换为可解析的 xml 结构,这就是我的答案。所以请阅读它。
【解决方案3】:

xmlValue获取节点的值并替换。这里我将把 ABC 换成 DEF:

> top<-xmlRoot(doc)
> top
<Text>
    &lt;p&gt;ABC &lt;/p&gt;
</Text> 
> xmlValue(top)=sub("ABC","DEF",xmlValue(top))
> top
<Text>
    &lt;p&gt;DEF &lt;/p&gt;
</Text> 

我不尝试替换

> substr(xmlValue(top),6,6)=="<"
[1] TRUE

虽然我尝试过使用 xmlTreeParse 和其他 XML 包函数的一些选项,但我似乎无法阻止 xmlValue 解释它们...

【讨论】:

  • Abc 只是一个例子,实际上我有一张桌子代替 ABC。我认为我们不能对整个表使用 xmlValue。
  • 是的,我的意思是替换这样的简单文本不是问题,这是解决方案,但是您的实体编码的 HTML 标记尖括号(&lt; 和 ' >`) 并没有像你想象的那样。
  • 我需要更换 >带有相应的标签。为此,我正在替换它。
  • XML 包正在为您替换编码的小于号和大于号。您需要更多帮助吗?
  • @Spacedman,我正在尝试实现此 [sharepoint.stackexchange.com/questions/73401/…,以签入我使用 curl 从 Rshiny 服务器上运行的闪亮应用程序上传到 SharePoint 的文件。文件名将更改,因此我无法使用存储的 xml。您有什么方法可以建议我实现这一目标吗?
猜你喜欢
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
相关资源
最近更新 更多