gpt4 book ai didi

java - namespace 和 JDOM

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:09:47 24 4
gpt4 key购买 nike

我当前的代码是这样打印出 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");

}

最佳答案

在 XML 文档中,如果您将 xmlns="http://a.b.c" 添加到一个元素,那么该元素及其所有后代元素将位于命名空间 "http://a.b.c",除非后代元素碰巧改变了xmlns声明。这意味着,在 XML 文档中,默认 namespace “级联”到后代。这个过程很“方便”,因此 XML 不会那么“困惑”。 “默认”命名空间是没有前缀的命名空间。将默认命名空间设置为某个值 "http://a.b.c" 的父元素的子元素位于该命名空间中,即使它们没有 xmlns="http://a.b.c" 在他们的标签行上声明。

当 JDOM 像这样对文档建模时,它会将每个元素节点的 namespace 设置为它应该的确切值。它不会“计算”或“级联”元素的 namespace 。在 JDOM 中,如果您更改父元素的 namespace ,它也不会更改子元素的 namespace 。因此,例如,如果您有:

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

然后您在默认命名空间 "http://a.b.c" 中同时拥有 rootchild。该文档可以在 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>

现在,如果您更改根的命名空间:

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 命名空间。您的代码可能看起来像这样(注意我添加到 new Element(...) 的所有 , ns)...

请参阅 Element(String) 的 JavaDoc , 以及 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……命名空间的本质就是它的复杂性。

关于java - namespace 和 JDOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21778987/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com