2015-10-04 50 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>