【问题标题】:Creating XML in R with namespaces在 R 中使用命名空间创建 XML
【发布时间】:2016-01-01 13:21:16
【问题描述】:

我正在尝试在 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>

但是如果我添加一个默认的(未命名的)命名空间,那么为内部元素设置命名空间就没有任何作用。将上面的一行更改为:

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)构建它们。

【问题讨论】:

    标签: xml r namespaces


    【解决方案1】:

    看起来addNodenamespace 参数为此被忽略了,但这里有一个解决方法:

    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 函数。

    【讨论】:

    • 您可以通过执行setXMLNamespace(z$addNode("Name","My Layer"),"se") 来消除nameNode 变量,甚至可以使用管道:z$addNode("Name","My Layer") %&gt;% setXMLNamespace("se")
    【解决方案2】:

    这里有一个轻微的变体,它也保留了默认的命名空间。 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-06
      • 2011-03-17
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      相关资源
      最近更新 更多