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);
}
}
참고 수행하는 코드를 THIE 무엇을, 수동으로 그 때의 DOM에서 JDOM을 구축 출력, 출력, DOM을 구축 할 것을 DOM을 문자열로 출력하고 DOM을 String으로 다시 구문 분석 한 다음 다시 파싱 한 XML에서 JDOM을 빌드합니다.
이
<?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이 생성된다 :
이
는 출력 (I 실제 DOM 문자열이 자신의 라인에 XML 선언을하기 위해 수동으로 출력에 줄 바꿈을 넣어)입니다 출력은 기술적으로 "네임 스페이스 인식"이 아니므로 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)을 만들었습니다 : 현재 DOM과 JDOM 내용의 불편한 혼합이 https://github.com/hunterhacker/jdom/issues/138
.... 주'그 root'는 DOM이 아닌 JDOM 요소이며, JDOM하지 않습니다 이러한 불법 이름으로 속성을 설정할 수 있습니다. 왜 JDOM 문서로 직접 문서를 만들지 않고 이런 식으로 일을하고 있습니까? – rolfl
특별한 이유가 없습니다. 레거시 코드의 무리. 코드의 일부 주석에 따르면 JDOM은 XML을 형식화하는 데만 사용되는 것처럼 보입니다. JDOM 1.0 덕분에 잘 작동했습니다. 힌트를 가져 주셔서 감사합니다! – Roland
유스 케이스를 찾고 있는데 DOMBuilder에서 속성 네임 스페이스를 선택하지 않은 버그를 발견했을 수 있습니다. 내가 그걸 확인하기 전에 오늘 일을 끝내기를 기다려야 할 것 같다. 당신이 가지고있는 용도는 다소 이례적입니다. 그냥 말해. – rolfl