пространства имен и JDOM

мой текущий код распечатывает xml следующим образом:

<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");

}

1 ответов


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

когда JDOM моделирует такой документ,он устанавливает пространство имен каждого узла элемента в точное значение, которое должно быть. Он не "вычисляет" или "каскадирует" пространство имен элемента. В 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 будет, как и ожидалось:

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

теперь, если вы измените пространство имен 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 для Элемент(Строку) и Элемент(Строка, Пространство Имен);.

    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 в этой путанице.... это природа пространств имен, что это сложно.