我试图从JDOM 1.0更新到JDOM2。在JDOM 1.0中,此代码:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
org.w3c.dom.Document doc = dbFactory.newDocumentBuilder().newDocument();
doc.setXmlVersion("1.0");
Element root = doc.createElement("Document");
root.setAttribute("xmlns", "urn:iso:foo");
root.setAttribute("xsi:schemaLocation", "urn:iso:foo bar.xsd");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
doc.appendChild(root);
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("testxml.xml"), "UTF8"));
DOMBuilder builder = new DOMBuilder();
Document jdoc = builder.build(doc);
XMLOutputter fmt = new XMLOutputter();
fmt.setFormat(Format.getPrettyFormat());
fmt.output(jdoc, out);
生成此XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:foo bar.xsd" />
当我使用JDOM2时,属性xsi:schemaLocation
更改为schemaLocation
(XML看起来像这样):
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="urn:iso:foo bar.xsd" />
有没有办法将xsi:
零件保留在JDOM2中?没有它,处理生成的XML的系统将无法读取它(不在我的控制之下)。不确定这是否是相同的问题。
JDOM要求使用支持名称空间的DOM实现来构建JDOM文档。
我整理了以下代码来说明这一点:
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.jdom2.Document;
import org.jdom2.input.DOMBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
public class DOMvsJDOM {
private static org.w3c.dom.Document buildDOM(String xml) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(false);
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(xml);
InputSource is = new InputSource(sr);
return db.parse(is);
}
public static void printDocument(org.w3c.dom.Document doc, OutputStream out) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}
private static void parseUsingJDOM(org.w3c.dom.Document doc) throws Exception {
// Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("testxml.xml"), "UTF8"));
DOMBuilder builder = new DOMBuilder();
Document jdoc = builder.build(doc);
XMLOutputter fmt = new XMLOutputter();
fmt.setFormat(Format.getPrettyFormat());
fmt.output(jdoc, System.out);
}
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
org.w3c.dom.Document doc = dbFactory.newDocumentBuilder().newDocument();
doc.setXmlVersion("1.0");
Element root = doc.createElement("Document");
root.setAttribute("xmlns", "urn:iso:foo");
root.setAttribute("xsi:schemaLocation", "urn:iso:foo bar.xsd");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
doc.appendChild(root);
printDocument(doc, System.out);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
printDocument(doc, baos);
System.out.println("JDOM Using captured");
parseUsingJDOM(doc);
String xml = new String(baos.toByteArray());
doc = buildDOM(xml);
System.out.println("JDOM Using parsed");
parseUsingJDOM(doc);
}
}
请注意,该代码的作用是手动构建DOM,将其输出,从DOM构建JDOM,将其输出,然后将DOM作为字符串输出,将String重新解析为DOM,然后从重新构建JDOM。解析的XML。
这是输出(我在输出中手动添加了换行符,以使实际的DOM字符串在其自己的行上具有XML声明):
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:foo bar.xsd"/>
JDOM Using captured
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="urn:iso:foo bar.xsd" />
JDOM Using parsed
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:foo bar.xsd" />
最重要的是,产生输出的DOM从技术上讲不是“名称空间感知”的,因此不能满足JDOM 2.0的期望。
现在,您使用以下代码来设置属性:
root.setAttribute("xmlns", "urn:iso:foo"); root.setAttribute("xsi:schemaLocation", "urn:iso:foo bar.xsd"); root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
如果改用支持名称空间的版本:
root.setAttribute("xmlns", "urn:iso:foo");
root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation", "urn:iso:foo bar.xsd");
doc.appendChild(root);
然后JDOM会正确处理。
这就是JDOM在上面的“从字符串解析”版本中工作的原因,因为解析是通过名称空间感知的方式完成的。
因此,JDOM要求在处理DOM内容时,DOM内容应采用可识别XML命名空间的格式。这就是为什么我的测试都可以工作的原因,因为我的DOM内容都可以识别名称空间。
不幸的是,这不能解决您遇到的实际问题。
在这种情况下,JDOM2应该与JDOM 1.x兼容,并且不兼容是一个问题。JDOM2正在做“正确”的事情,但它也可能也应该做“错误”的事情,并坚持为未正确声明的DOM上定义的那些属性寻找名称空间。
我创建了第138期来对此进行跟踪:https : //github.com/hunterhacker/jdom/issues/138
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句