如何编写带有特殊字符的 xml 代码(使用 R xml 包)
How to write xml code (using R xml package) with special characters
我正在尝试编写特定程序需要的一些 xml 文件,但在某些文本中写入 'special characters' 时遇到问题,因此程序抛出错误。
如何将特殊字符(特别是“>”)写入标签的属性?
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 - > +6-0-0"
我认为应该使用这些方法,但还没有找到解决方法...
xmlCDataNode()
# or
xml$addCData
次要问题 - 如何为每个标签缩进一个新行?
xml header 有自己的行,但除此之外,所有标签都水平堆叠在同一行中。我希望每个新标签都换行(我正在使用记事本++或其他编辑器查看代码)。
某些字符,特别是 <
和 &
,必须始终进行转义。如果您的库没有转义这些字符,输出将不会是格式正确的 XML 并且将无法使用。
其他字符,如>
、"
和'
,需要在特定条件下转义,许多库会无条件转义它们,因为这是最简单的事情做,一旦你把 XML 通过解析器,它就没有任何区别了。如果你真的希望 >
不被转义,你应该问问自己为什么。仅仅是出于审美原因吗?如果下游软件依赖于它未被转义,那么下游软件就是有问题的 - 并且编写 XML 可以被有问题的客户端消耗,这会导致大量的 Whosebug 流量,所以你手上有问题。
我被要求解决这个问题,因为我是 XML 包的作者。
正如迈克尔所说,如果属性是
time = "2000-01-01/1 -> +6-0-0"
虽然 xmlParse() 和 libxml2 会正确地解析它并将 > 转换为 >,但它的格式是错误的 XML字符序列。
有趣的是,> 字符没有转换为 >当我们创建属性时:
z = newXMLNode("bob", attrs = c(a = "x > y"))
xmlGetAttr(z, "a")
[1] "x > y"
转换发生在对 saveXML() 的调用中。因此,原则上,您可以避免 saveXML() 并编写 R 代码来遍历树并自己生成输出,以您想要的方式处理每个属性。但是,这是最后的手段。
尽管我讨厌使用正则表达式来处理 XML,但我建议您 post- 处理 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>
如果可以替换all>就比较简单了与>。如果您需要更换 >对于某些上下文中出现的部分子集,您的正则表达式必须更复杂。
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 文件,但在某些文本中写入 'special characters' 时遇到问题,因此程序抛出错误。
如何将特殊字符(特别是“>”)写入标签的属性?
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 - > +6-0-0"
我认为应该使用这些方法,但还没有找到解决方法...
xmlCDataNode()
# or
xml$addCData
次要问题 - 如何为每个标签缩进一个新行?
xml header 有自己的行,但除此之外,所有标签都水平堆叠在同一行中。我希望每个新标签都换行(我正在使用记事本++或其他编辑器查看代码)。
某些字符,特别是 <
和 &
,必须始终进行转义。如果您的库没有转义这些字符,输出将不会是格式正确的 XML 并且将无法使用。
其他字符,如>
、"
和'
,需要在特定条件下转义,许多库会无条件转义它们,因为这是最简单的事情做,一旦你把 XML 通过解析器,它就没有任何区别了。如果你真的希望 >
不被转义,你应该问问自己为什么。仅仅是出于审美原因吗?如果下游软件依赖于它未被转义,那么下游软件就是有问题的 - 并且编写 XML 可以被有问题的客户端消耗,这会导致大量的 Whosebug 流量,所以你手上有问题。
我被要求解决这个问题,因为我是 XML 包的作者。 正如迈克尔所说,如果属性是
time = "2000-01-01/1 -> +6-0-0"
虽然 xmlParse() 和 libxml2 会正确地解析它并将 > 转换为 >,但它的格式是错误的 XML字符序列。
有趣的是,> 字符没有转换为 >当我们创建属性时:
z = newXMLNode("bob", attrs = c(a = "x > y"))
xmlGetAttr(z, "a")
[1] "x > y"
转换发生在对 saveXML() 的调用中。因此,原则上,您可以避免 saveXML() 并编写 R 代码来遍历树并自己生成输出,以您想要的方式处理每个属性。但是,这是最后的手段。
尽管我讨厌使用正则表达式来处理 XML,但我建议您 post- 处理 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>
如果可以替换all>就比较简单了与>。如果您需要更换 >对于某些上下文中出现的部分子集,您的正则表达式必须更复杂。
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
部分。