2015-10-04 49 views
3

我试图在R中构建一个如下所示的XML结构。注意默认名称空间,其它的命名空间,并且内Name对象,它是在可替换的名称空间:使用命名空间在R中创建XML

<?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> 

但是,如果我添加一个默认(未命名)命名空间,然后设置命名空间内构件什么都不做。更改一行上面:

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)。

回答

1

貌似namespace参数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无形返回节点的事实。我们将该值分配给临时对象,所以我们可以在该对象上使用setXMLNamespace函数。

+0

您可以通过执行'setXMLNamespace(Z $ ADDNODE( “姓名”, “我的层”), “SE”)',甚至管它消除了'nameNode'变量:'Z $ ADDNODE(”名称“,”我的图层“)%>%setXMLNamespace(”se“)'。 – Spacedman

1

这是一个稍微的变体,它也保留了默认的名称空间。 FWIW我认为XML::newXMLNode()(在我的代码中)和z$addNode(在另一个答案中)与DTL书(?)中的文档和示例相反。你应该能够在这里指定“se”命名空间,并通过祖先中的命名空间定义来解决它。但似乎并非如此。

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>