【问题标题】:adding namespace and namespace prefix using dom4j使用 dom4j 添加命名空间和命名空间前缀
【发布时间】:2012-10-22 22:05:11
【问题描述】:

我正在使用 dom4j 更新一个 xml,如下所示。

    SAXReader reader = new SAXReader();
document = reader.read( xmlFileName );

但它会从元素中删除所有命名空间,因此想手动添加,但当我尝试以下代码时它不起作用。

    Element e1 = root.addElement("jmsProducer");   
    e1.addNamespace("AEService", "http://www.tibco.com/xmlns/aemeta/services/2002");

我的 xml 看起来像

    <AEService:jmsProducer objectType="endpoint.JMSPublisher" name="Pub1EndPoint">  
    <AEService:wireFormat>aeXml</AEService:wireFormat>

sud 看起来像什么

    <AEService:jmsProducer xmlns:AEService="http://www.tibco.com/xmlns/aemeta/services   /2002" objectType="endpoint.JMSPublisher" name="Pub1EndPoint">
    <AEService:wireFormat>aeXml</AEService:wireFormat>

非常感谢任何帮助。敲了两天尝试使用documentfactory方法仍然没有用。

【问题讨论】:

    标签: java xml-parsing xml-namespaces dom4j


    【解决方案1】:

    我意识到这是一个旧线程,并且在编写答案时 dom4j 可能没有足够的命名空间功能,但看起来 dom4j 现在可以使用我使用的版本(1.6 .1)。我来这里寻求有关如何使用 dom4j 构建命名空间感知 XML 的帮助,发布我的 Java 代码(在原始帖子中构建 XML sn-p)以防它对某人有所帮助。

    这是构建它的 Java 代码。

    Document xmldoc = DocumentHelper.createDocument();
    Namespace aeServiceNs = new Namespace("AEService",
      "http://www.tibco.com/xmlns/aemeta/services/2002");
    Element root = xmldoc.addElement(new QName("jmsProducer", aeServiceNs))
                         .addAttribute("objectType", "endpoint.JMSPublisher")
                         .addAttribute("name", "Pub1EndPoint");
    Element wireformat = root.addElement(new QName("wireFormat", aeServiceNs))
                             .setText("aeXml");
    OutputFormat outputFormat = OutputFormat.createPrettyPrint();
    XMLWriter xmlwriter = new XMLWriter(System.out, outputFormat);
    xmlwriter.write(xmldoc);
    

    产生这个输出:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <AEService:jmsProducer 
        xmlns:AEService="http://www.tibco.com/xmlns/aemeta/services/2002" 
        objectType="endpoint.JMSPublisher" name="Pub1EndPoint">
      <AEService:wireFormat>aeXml</AEService:wireFormat>
    </AEService:jmsProducer>
    

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我建议你转储 dom4j 并使用 JAXB 或 StAX。如果您不能这样做,请尝试以下操作(我没有验证这一点,所以将后续问题作为 cmets 发布)

      Namespace ns = new Namespace("AEService","http://www.tibco.com/xmlns/aemeta/services/2002")
      document.add(ns);
      

      【讨论】:

      • 我无法添加到文档本身出现异常但是当添加到元素时它没有添加但是当我尝试命名空间 ns = new Namespace(":AEService","tibco.com/xmlns/aemeta/services/2002") 然后 xml如果可以以某种方式删除多余的冒号,我的工作就会完成。
      • 由于您的代码,该额外的列即将到来。将命名空间 ns = new Namespace(":AEService","tibco.com/xmlns/aemeta/services/2002") 更改为命名空间 ns = new Namespace("AEService","tibco.com/xmlns/aemeta/services/2002" )
      • 您在 AEService 之前有一个冒号,因此创建了一个额外的冒号
      • 是的,我知道我添加了额外的冒号,因为当我不添加时,我会像命名空间 ns = new Namespace("AEService","tibco.com/xmlns/aemeta/services/2002")它根本不添加任何命名空间:(...有些棘手...
      【解决方案3】:

      我发现为了正确设置命名空间,需要在整个节点层次结构上递归设置。

      这两种方法可以解决问题:

         /**
          * Recursively sets the namespace of the element and all its children.
          */
         private void setNamespaces( Element elem, Namespace ns ) {
            setNamespace( elem, ns );
            setNamespaces( elem.content(), ns );
         }
      
         /**
          * Recursively sets the namespace of the List and all children if the
          * current namespace is match
          */
         private void setNamespaces( List l, Namespace ns ) {
            Node n = null;
            for ( int i = 0; i < l.size(); i++ ) {
               n = ( Node ) l.get( i );
      
               if ( n.getNodeType() == Node.ATTRIBUTE_NODE ) {
                  (( Attribute ) n).setNamespace( ns );
               }
               if ( n.getNodeType() == Node.ELEMENT_NODE ) {
                  setNamespaces( ( Element ) n, ns );
               }
            }
         }
      

      然后我可以像这样添加命名空间:

      setNamespaces( ( Element ) xml.selectSingleNode( "/root/settings" ),
                        new Namespace( "", "http://www.penvision.se/printprocessor" ) );
      

      希望对你有帮助

      【讨论】:

        【解决方案4】:

        我可以通过以下步骤在子元素而不是根元素处添加命名空间:

        1. 使用 xpath 从创建的文档中查找节点。

        2. 创建名称空间前缀名称和值。

        3. 将元素添加到节点中,如下所示:

          Document document = DocumentHelper.createDocument();
          Element documentRoot = null;
          
          Element created = null;
          
          Node parentNode = null;
          documentRoot = DocumentHelper.createElement();
          parentNode = documentRoot.selectSingleNode("parentXPath");
          Namespace ns = new Namespace("name","value");
          created = ((Element) parentNode).addElement(new QName("elementName",ns1));
          

        【讨论】:

        • 您声明了变量 ns 并且不使用它。您还使用变量ns1,但您没有声明它。我怀疑它甚至会编译为 sn-p。
        【解决方案5】:

        使用库dom4j:2.1.1

        初始化文档后:

        SAXReader reader = new SAXReader();
        reader.getDocumentFactory().setXPathNamespaceURIs(ImmutableMap.of("x", "DAV:"));
        Document doc = reader.read(new StringReader(xmlContent));
        doc.getRootElement().selectNodes("//x:response")
        

        我可以用命名空间x: 作为XPath 表达式的前缀。

        注意:不允许使用空的命名空间。您需要指定一个前缀。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多