赏金:目前的答案还没有完全解决。
更新:非常欢迎我尝试将“ R转换为R”的非R答案!
类似于How to deal with single quote in xpath,我想转义单引号。区别在于我无法排除在目标字符串中也可能出现双引号的可能性。
目标:
同时使用xpath(在R中,转义双引号和单引号)。目标元素应该用作变量,而不像现有答案之一那样被硬编码。 (它应该是一个变量,因为我事先不知道Content,它可以有单引号,双引号或两者都有)。
Works:
library(rvest)
library(magrittr)
html <- "<div>1</div><div>Father's son</div>"
target <- "Father's son"
html %>% xml2::read_html() %>% html_nodes(xpath = paste0("//*[contains(text(), \"", target,"\")]"))
{xml_nodeset (1)}
[1] <div>Father's son</div>
不起作用:
html <- "<div>1</div><div>Fat\"her's son</div>"
target <- "Fat\"her's son"
html %>% xml2::read_html() %>% html_nodes(xpath = paste0("//*[contains(text(), \"", target,"\")]"))
{xml_nodeset (0)}
Warning message:
In xpath_search(x$node, x$doc, xpath = xpath, nsMap = ns, num_results = Inf) :
Invalid expression [1207]
将quote()
用于xpath查询
library(XML)
字符串中仅单引号
target1 <- "Father's son"
doc1 <- XML::newHTMLDoc()
newXMLNode("div", 1, parent = getNodeSet(doc1, "//body"), doc = doc1)
newXMLNode("div", target1, parent = getNodeSet(doc1, "//body"), doc = doc1)
xpath_query1 <- paste0('//*[ contains(text(), ', '"', target1, '"', ')]')
getNodeSet(doc1, xpath_query1)
字符串中的单引号和双引号都包含
target2 <- "Fat\"her's son"
doc2 <- XML::newHTMLDoc()
newXMLNode("div", 1, parent = getNodeSet(doc2, "//body"), doc = doc2)
newXMLNode("div", target2, parent = getNodeSet(doc2, "//body"), doc = doc2)
xpath_query2 <- quote('//body/*[contains(.,concat(\'Fat"\',"her\'s son"))]')
getNodeSet(doc2, xpath_query2)
输出:
getNodeSet(doc1, xpath_query1)
# [[1]]
# <div>Father's son</div>
#
# attr(,"class")
# [1] "XMLNodeSet"
getNodeSet(doc2, xpath_query2)
# [[1]]
# <div>Fat"her's son</div>
#
# attr(,"class")
# [1] "XMLNodeSet"
由于您正在使用字符串操作来构建XPath表达式,因此该表达式是有效的XPath是您的责任。这个表达式:
//*[contains(.,concat('Fat"',"her's son"))]
选择:
<div>Fat"her's son</div>
在here中测试
使用XPath字符串变量是一种更好的方法,但是看起来R甚至没有使用libxml的API。