使用命名空间

时间:2015-10-04 22:55:02

标签: xml r namespaces

我正在尝试在R中构建一个看起来像这样的XML结构。请注意默认命名空间,其他命名空间以及备用命名空间中的内部Name对象:

<?xml version = "1.0" encoding="UTF-8"?>
<sld xmlns="http://www.o.net/sld" 
     xmlns:ogc="http://www.o.net/ogc" 
     xmlns:se="http://www.o.net/se"
     version="1.1.0" >
<layer>
<se:Name>My Layer</se:Name>
</layer>
</sld>

这段代码很接近,标签上的命名空间没问题,但根标签中没有默认命名空间:

require(XML)
makesimple = function(){
    z = xmlTree("sld",
                namespaces=list(
                    "ogc"="http://www.o.net/ogc",
                    "se"="http://www.o.net/se"),
                attrs=list(version="1.1.0")
                )
    z$addNode("layer", close=FALSE)
    z$setNamespace("se")
    z$addNode("Name","My Layer")
    z$closeTag()
    z
}
> cat(saveXML(makesimple()))

给出

<?xml version="1.0"?>
 <sld 
  xmlns:ogc="http://www.o.net/ogc"
  xmlns:se="http://www.o.net/se" 
  version="1.1.0">
  <layer>
    <se:Name>My Layer</se:Name>
  </layer>
</sld>

但是如果我添加一个默认(未命名)命名空间,那么为inner元素设置命名空间什么也不做。将上面的一行更改为:

z = xmlTree("sld",
            namespaces=list("http://www.o.net/sld",
                "ogc"="http://www.o.net/ogc",
                "se"="http://www.o.net/se"),
            attrs=list(version="1.1.0")
            )

这让我:

<?xml version="1.0"?>
  <sld 
    xmlns="http://www.o.net/sld" 
    xmlns:ogc="http://www.o.net/ogc"
    xmlns:se="http://www.o.net/se"
   version="1.1.0">
  <layer>
    <Name>My Layer</Name>
  </layer>
</sld>

它的根元素中的所有命名空间都是正确的,但是内部元素所需的命名空间已经消失了。

注意我开始使用newXMLDocnewXMLNode函数开始处理此问题,直到我阅读了以下文档:

 While the
 functions are available, their direct use is not encouraged.
 Instead, use ‘xmlTree’ as the functions need to be used within a
 strict regime to avoid corrupting C level structures.

我正在放弃使用package::XML构建这些内容并使用模板系统构建它们(可能是package::brew)。

2 个答案:

答案 0 :(得分:1)

为此目的,namespace的{​​{1}}参数似乎被忽略了,但这是一个解决方法:

addNode

基本上,我们使用require(XML) makesimple = function(){ z = xmlTree("sld", namespaces=list("http://www.o.net/sld", "ogc"="http://www.o.net/ogc", "se"="http://www.o.net/se"), attrs=list(version="1.1.0") ) z$addNode("layer", close=FALSE) # addNode returns the node invisibly, assign so we can use it nameNode <- z$addNode("Name","My Layer") setXMLNamespace(nameNode, "se") z$closeTag() z } cat(saveXML(makesimple())) # <?xml version="1.0"?> # # <sld xmlns:ogc="http://www.o.net/ogc" xmlns:se="http://www.o.net/se" version="1.1.0"> # <layer> # <se:Name>My Layer</se:Name> # </layer> # </sld> 无形地返回节点的事实。我们将该值赋给临时对象,因此我们可以在该对象上使用addNode函数。

答案 1 :(得分:1)

这是一个轻微的变体,它也保留了默认的命名空间。 FWIW我认为XML::newXMLNode()(在我的代码中)和z$addNode(在另一个答案中)与DTL的书(?)中的文档和示例背道而驰。你应该能够指定&#34; se&#34;命名空间在这里,让它通过祖先的命名空间定义解决。但事实似乎并非如此。

library(XML)

makesimple <- function() {
  z <- newXMLNode("sld", newXMLNode("layer"), attrs = list(version="1.1.0"),
                  namespaceDefinitions = c("http://www.o.net/sld",
                                           ogc = "http://www.o.net/ogc",
                                           se = "http://www.o.net/se"))
  z_doc <- newXMLDoc(node = z)
  Name <- newXMLNode("Name", "My Layer", parent = z[["layer"]])
  setXMLNamespace(Name, "se")
  z_doc
}
cat(saveXML(makesimple()))
#> <?xml version="1.0"?>
#> <sld xmlns="http://www.o.net/sld" xmlns:ogc="http://www.o.net/ogc" xmlns:se="http://www.o.net/se" version="1.1.0">
#>   <layer>
#>     <se:Name>My Layer</se:Name>
#>   </layer>
#> </sld>

强制命名空间解析的另一种方法似乎是在创建节点时指定命名空间前缀,但是不指定父节点。然后,当节点作为子节点添加时,命名空间确实可以从祖先正确解析。

library(XML)

makesimple2 <- function() {
  z <- newXMLNode("sld", newXMLNode("layer"), attrs=list(version="1.1.0"),
                  namespaceDefinitions = c("http://www.o.net/sld",
                                           ogc = "http://www.o.net/ogc",
                                           se = "http://www.o.net/se"))
  z_doc <- newXMLDoc(node = z)
  Name <- newXMLNode("se:Name", "My Layer")
  addChildren(z[["layer"]], Name)
  z_doc
}
cat(saveXML(makesimple2()))
#> <?xml version="1.0"?>
#> <sld xmlns="http://www.o.net/sld" xmlns:ogc="http://www.o.net/ogc" xmlns:se="http://www.o.net/se" version="1.1.0">
#>   <layer>
#>     <se:Name>My Layer</se:Name>
#>   </layer>
#> </sld>