我当前的代码是打印出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");
}
答案 0 :(得分:7)
在XML文档中,如果向元素添加xmlns="http://a.b.c"
,那么该元素及其所有后代元素将位于命名空间"http://a.b.c"
中,除非后代元素恰好更改{ {1}}声明。这意味着,在XML文档中,默认命名空间“级联”到后代。这个过程是一个“便利”,因此XML不会“混乱”。 'default'命名空间是没有前缀的命名空间。将默认命名空间设置为某个值xmlns
的父项的子元素是'在'该命名空间中,即使它们的标记行上没有"http://a.b.c"
声明。
当JDOM为这样的文档建模时,它会将每个Element节点的Namespace设置为它应该具有的确切值。它不会“计算”或“级联”元素的命名空间。在JDOM中,如果更改父元素的命名空间,它也不会更改子元素的命名空间。所以,例如,如果你有:
xmlns="http://a.b.c"
然后,您在默认的命名空间<root xmlns="http://a.b.c">
<child />
</root>
中同时拥有root
和child
。该文档可以在JDOM中创建为:
"http://a.b.c"
注意ns是如何添加到两个元素的。这个JDOM的输出将如下所示:
Namesapce ns = Namespace.get("http://a.b.c");
Element root = new Element("root", ns);
Element child = new Element("child", ns);
root.addConent(child);
现在,如果您更改root的命名空间:
<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>
而不是new Element("tag")
的JDOM元素时,JDOM会自动将新元素放入NO_NAMESPACE名称空间(与new Element("tag", Namespace)
相同)。这就是你在做什么。
所以,JDOM正在做你要求它做的事情......但你要求它做的事情似乎并不像你想要的那样。
你说你想要的是:
new Element("tag", Namespace.NO_NAMESPACE);
上述XML在命名空间<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>
中包含所有内容。
您的代码将大量内容放入NO_NAMESPACE命名空间中。您的代码可能看起来像这样(请注意我添加到Namespace.getNamespace("http://www.example.com")
的所有, ns
)...
请参阅JavaDoc以了解Element(String)和Element(String, Namespace);。
new Element(...)
在上面的代码中,一切位于 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");
命名空间中,因此,JDOM只需要输出带有"http://www.example.com"
声明的顶级元素,你应该得到你想要的。
对于它的价值,你不仅可以将JDOM归咎于这种混乱......它是命名空间的本质,它很复杂。