2014-02-14 3 views
6

Мой текущий код распечатав XML так:пространств имен и JDOM

<type xmlns="http://www.example.com"> 
    <OBJECT_TYPE xmlns="">x3000</OBJECT_TYPE> 
- <prop xmlns=""> 
    <DESCRIPTION>a very fast train</DESCRIPTION> 
    <PARENT>NULL</PARENT> 
    <VIRTUAL>0</VIRTUAL> 
    <VISIBLE>1</VISIBLE> 
    <PICTURE>NULL</PICTURE> 
    <HELP>NULL</HELP> 
    <MIN_NO>NULL</MIN_NO> 
    <MAX_NO>NULL</MAX_NO> 
    <NAME_FORMAT>NULL</NAME_FORMAT> 
    </prop> 
</type> 

Но я хочу этот вывод:

<type xmlns="http://www.example.com"> 
    <OBJECT_TYPE>x3000</OBJECT_TYPE> 
- <prop> 
    <DESCRIPTION>a very fast train</DESCRIPTION> 
    <PARENT>NULL</PARENT> 
    <VIRTUAL>0</VIRTUAL> 
    <VISIBLE>1</VISIBLE> 
    <PICTURE>NULL</PICTURE> 
    <HELP>NULL</HELP> 
    <MIN_NO>NULL</MIN_NO> 
    <MAX_NO>NULL</MAX_NO> 
    <NAME_FORMAT>NULL</NAME_FORMAT> 
    </prop> 
</type> 

Как сделать это? Это мой текущий код:

public void saveXmlToFile(Type objType, Properties property) 
    throws IOException, ParserConfigurationException, SAXException, 
    JDOMException { 

     File xmlFile = new File(XMLEditorService.getXMLEditorService() 
       .getFile()); 
     org.jdom2.Document doc = new SAXBuilder().build(xmlFile); 
     Element root = doc.getRootElement(); 
     Namespace ns = Namespace.getNamespace("http://www.example.com"); 
     Element type = new Element("type"); 
     Element prop = new Element("prop"); 

     // Add <type> as a child of <root> 
     root.addContent(type); 

     // Set namespace on <type> 
     type.setNamespace(ns); 

     type.addContent(new Element("OBJECT_TYPE").setText(objType.getObjectType())); 

     // Turn off namespace on <prop> 
     prop.setNamespace(Namespace.NO_NAMESPACE); 

     // Add <prop> as a child of <type> 
     type.addContent(prop); 

     prop.addContent(new Element("DESCRIPTION").setText(property.getDescription())); 
     prop.addContent(new Element("PARENT").setText(property.getParent())); 
     prop.addContent(new Element("VIRTUAL").setText(property.getVirtual())); 
     prop.addContent(new Element("VISIBLE").setText(property.getVisible())); 
     prop.addContent(new Element("PICTURE").setText(property.getPicture())); 
     prop.addContent(new Element("HELP").setText(property.getHelp())); 
     prop.addContent(new Element("MIN_NO").setText(property.getMin_no())); 
     prop.addContent(new Element("MAX_NO").setText(property.getMax_no())); 
     prop.addContent(new Element("NAME_FORMAT").setText(property.getName_format())); 

     XMLOutputter xmlOutput = new XMLOutputter(Format.getPrettyFormat()); 
     // Create a new file and write XML to it 
     xmlOutput.output(doc, new FileOutputStream(new File(XMLEditorService.getXMLEditorService().getFile()))); 
     System.out.println("Wrote to file"); 

} 

ответ

7

В документе XML, если добавить xmlns="http://a.b.c" к элементу, то этому элементу, и все эти элементы-потомкам, будет находиться в пространстве имен "http://a.b.c", если узлы не произойдут изменить декларация xmlns. Это означает, что в XML-документе пространство имен по умолчанию «каскады» для потомков. Этот процесс является «удобством», так что XML не является «загроможденным». Пространство имен «по умолчанию» - это пространство имен, которое не имеет префикса. Элементы дочернего элемента родителя, который задает пространство имен по умолчанию для некоторого значения "http://a.b.c", находятся в этом пространстве имен, даже если они не имеют объявления xmlns="http://a.b.c" на своей строке тегов.

Когда JDOM моделирует такой документ, он устанавливает пространство имен каждого элемента Element точно, какое оно должно быть. Он не «вычисляет», а «каскадирует» пространство имен элемента. В JDOM, если вы измените пространство имен родительского элемента, оно также не изменит пространства имен дочерних элементов. Так, например, если у вас есть:

<root xmlns="http://a.b.c"> 
    <child /> 
</root> 

Тогда у вас есть и root и child в пространстве имен по умолчанию "http://a.b.c". Этот документ можно было бы создать в JDOM, как:

Namesapce ns = Namespace.get("http://a.b.c"); 
Element root = new Element("root", ns); 
Element child = new Element("child", ns); 
root.addConent(child); 

Обратите внимание, что ns добавлен к обоим элементам. Выход этого JDOM будет, так как expeced:

<root xmlns="http://a.b.c"> 
    <child /> 
</root> 

Теперь, если изменить пространство имен в суперпользователя:

Namesapce ns = Namespace.get("http://a.b.c"); 
Element root = new Element("root", ns); 
Element child = new Element("child", ns); 
root.addConent(child); 
root.setNamespace(Namespace.NO_NAMESPACE); 

вы получите:

<root> 
    <child xmlns="http://a.b.c"/> 
</root> 

Но, что более интересно, если вы покинете пространство имен корней и измените пространство имен детей,

Namesapce ns = Namespace.get("http://a.b.c"); 
Element root = new Element("root", ns); 
Element child = new Element("child", ns); 
root.addConent(child); 
child.setNamespace(Namespace.NO_NAMESPACE); 

вы получите:

<root xmlns="http://a.b.c"> 
    <child xmlns="" /> 
</root> 

При создании JDOM элемента без имен аргумента new Element("tag") вместо new Element("tag", Namespace) тогда JDOM автоматически поместит новый элемент в пространстве имен NO_NAMESPACE (так же, как new Element("tag", Namespace.NO_NAMESPACE);). Это то, что вы делаете.

Итак, JDOM делает то, что вы просите у него сделать ... но то, что вы просите, это не похоже на то, что вы хотите.

То, что вы говорите, что вы хотите, это:

<type xmlns="http://www.example.com"> 
    <OBJECT_TYPE>x3000</OBJECT_TYPE> 
- <prop> 
    <DESCRIPTION>a very fast train</DESCRIPTION> 
    <PARENT>NULL</PARENT> 
    <VIRTUAL>0</VIRTUAL> 
    <VISIBLE>1</VISIBLE> 
    <PICTURE>NULL</PICTURE> 
    <HELP>NULL</HELP> 
    <MIN_NO>NULL</MIN_NO> 
    <MAX_NO>NULL</MAX_NO> 
    <NAME_FORMAT>NULL</NAME_FORMAT> 
    </prop> 
</type> 

выше XML имеет все в пространстве имен Namespace.getNamespace("http://www.example.com").

Ваш код помещает много вещей в пространство имен NO_NAMESPACE. Ваш код должен, вероятно, выглядеть следующим образом (обратите внимание на все , ns я добавил к new Element(...)) ...

Смотрите JavaDoc для Element(String) и для Element(String, Namespace);.

org.jdom2.Document doc = new SAXBuilder().build(xmlFile); 
    Element root = doc.getRootElement(); 
    Namespace ns = Namespace.getNamespace("http://www.example.com"); 
    Element type = new Element("type", ns); 
    Element prop = new Element("prop", ns); 

    // Add <type> as a child of <root> 
    root.addContent(type); 

    // Set namespace on <type> 
    // type.setNamespace(ns); NO NEED, done on new Element("type", ns); above 

    type.addContent(new Element("OBJECT_TYPE", ns).setText(objType.getObjectType())); 

    // Turn off namespace on <prop> 
    // NO!!!! You want to keep the namespace ON!!! 
    // prop.setNamespace(Namespace.NO_NAMESPACE); 

    // Add <prop> as a child of <type> 
    type.addContent(prop); 

    prop.addContent(new Element("DESCRIPTION", ns).setText(property.getDescription())); 
    prop.addContent(new Element("PARENT", ns).setText(property.getParent())); 
    prop.addContent(new Element("VIRTUAL", ns).setText(property.getVirtual())); 
    prop.addContent(new Element("VISIBLE", ns).setText(property.getVisible())); 
    prop.addContent(new Element("PICTURE", ns).setText(property.getPicture())); 
    prop.addContent(new Element("HELP", ns).setText(property.getHelp())); 
    prop.addContent(new Element("MIN_NO", ns).setText(property.getMin_no())); 
    prop.addContent(new Element("MAX_NO", ns).setText(property.getMax_no())); 
    prop.addContent(new Element("NAME_FORMAT", ns).setText(property.getName_format())); 

    XMLOutputter xmlOutput = new XMLOutputter(Format.getPrettyFormat()); 
    // Create a new file and write XML to it 
    xmlOutput.output(doc, new FileOutputStream(new File(XMLEditorService.getXMLEditorService().getFile()))); 
    System.out.println("Wrote to file"); 

В приведенном выше коде, все находится в "http://www.example.com" пространстве имен, и, как следствие, JDOM нужно только вывести элемент верхнего уровня с xmlns декларации, и вы должны получить именно то, что вы хотите ,

Для чего это стоит, вы можете не только обвинять JDOM в этом замешательстве ... это природа пространств имен, что это сложно.

+0

Вы не добавили ', ns' ко всем' prop.addContent (....) ', как у меня в коде, не так ли? – rolfl

+0

yeh справа. Это отразилось на том, что я сделал. Это объяснение заслуживает большого внимания. один из лучших, что я когда-либо читал в Stackoverflow :-) – Sembrano

+1

@Sembrano это помогает, что я написал кусок этого кода .... вы должны были помочь мне несколько дней назад, когда я попросил дополнительную информацию ;-) Вместо удалив ваш вопрос, вы могли бы сэкономить массу стресса. – rolfl

Смежные вопросы