我正在尝试编写特定程序需要的一些xml文件,但在某些文本中写入"特殊字符"时遇到问题,因此程序会抛出错误。
如何将特殊字符(特别是">"(写入标记的属性
library(XML)
xml <- xmlTree()
xml$addTag("events", close=FALSE, attrs = c(PackageMinimumVersionRequired="1.3") )
# '>' is a special character that gets rewritten as '>'
xml$addTag("schedule", close=TRUE,
attrs = c(time = paste("2000-01-01/1 -> +6-0-0", sep='') ) )
xml$addTag('party', close=FALSE, attrs = c(number='1')) #just putting this in to show I have other nodes
xml$closeTag() # close party
xml$closeTag() # close events
saveXML(xml, file = "testfile.xml", encoding = "UTF-8" )
"time"属性被写成:time=";2000-01-01/1;gt+6-0-0";
我认为应该使用类似的东西,但还没能找到解决方案。。。
xmlCDataNode()
# or
xml$addCData
次要问题-如何为每个标记缩进到新行
xml头有自己的行,但除此之外,所有标记都水平堆叠在同一行中。我希望每个新标签都转到一行(我正在使用记事本++或其他编辑器查看代码(。
由于我是XML包的作者,所以我被要求解决这个问题。正如Michael所说,如果属性是
time = "2000-01-01/1 -> +6-0-0"
这将是格式错误的XML,尽管xmlParse((和libxml2将正确解析它并转换>到>;字符序列。
有趣的是;字符未转换为>;当我们创建属性时:
z = newXMLNode("bob", attrs = c(a = "x > y"))
xmlGetAttr(z, "a")
[1] "x > y"
转换发生在对saveXML((的调用中。因此,原则上,您可以避免saveXML((,并编写R代码来遍历树并自己生成输出,以您想要的方式处理每个属性。然而,这是最后的手段。
尽管我讨厌使用正则表达式来处理XML,但我建议您对saveXML((的输出进行后处理,如果您的内容是";"均匀";,替换所有>;对于>,即
cat(gsub(">", ">", saveXML(xml$value())))
<?xml version="1.0"?>
<events PackageMinimumVersionRequired="1.3">
<schedule time="2000-01-01/1 -> +6-0-0"/>
<party number="1"/>
</events>
如果您可以替换所有>;带有>。如果您需要更换>;对于某些上下文中仅出现的一个子集,正则表达式必须更加复杂。
Q2要在单独的行上获取节点并缩进,请使用
saveXML(xml$value(), "testfile.xml", encoding = "UTF-8")
即通过调用xml$value()
获取文档对象并保存。
顺便说一句,我的偏好是不使用xmlTree((及其函数集合(例如添加和关闭(,而是使用
doc = newXMLDoc()
e = newXMLNode("events", attrs = c(PackageMinimumVersionRequired="1.3") , doc = doc)
newXMLNode("schedule", attrs = c(time = paste("2000-01-01/1 -> +6-0-0", sep='')), parent = e)
您甚至可以选择放弃doc
部分。
某些字符,尤其是<
和&
,必须始终转义。如果您的库没有转义这些字符,那么输出将不是格式良好的XML,并且将不可用。
其他字符,如>
、"
和'
,需要在特定条件下进行转义,许多库都会无条件地对它们进行转义,因为这是最简单的操作,而且一旦将XML放入解析器,就不会有任何区别。如果你真的想让>
不受欢迎,你应该问问自己为什么。只是出于审美的原因吗?如果下游软件依赖于它的无屏蔽,那么下游软件就是有缺陷的——编写可被有缺陷的客户端使用的XML会占用大量StackOverflow流量,所以你会遇到问题。