XML dom을 생성하기 위해 파일을 읽는 동안 공백을 무시하는 방법
-
04-07-2019 - |
문제
DOM 문서를 생성하기 위해 파일을 읽으려고하지만 파일에는 공백과 신성경이 있으며 무시하려고하지만 할 수 없었습니다.
DocumentBuilderFactory docfactory=DocumentBuilderFactory.newInstance();
docfactory.setIgnoringElementContentWhitespace(true);
Javadoc에서 SetignoringElementContentWhitespace 메소드가 유효성 검사 플래그가 활성화 될 때만 작동하지만 문서의 DTD 또는 XML 스키마는 없습니다.
어떡해?
업데이트
나는 나 자신을 소개한다는 아이디어가 마음에 들지 않는다 <! element ... 선언은 제안 된 솔루션을 시도했다. 법정 Tomalak이 지적했지만 작동하지 않지만 Linux 환경에서 Java 1.6을 사용했습니다. 더 이상 제안되지 않으면 공백 텍스트 노드를 무시하는 몇 가지 방법을 만들 것입니다.
해결책
'무시하는 Whitespace를 무시하는 것은 제거에 관한 것이 아닙니다 모두 Pure-Whitespace 텍스트 노드, 부모가 스키마에 요소 컨텐츠가있는 것으로 스키마에 설명 된 공백 노드 만, 즉 다른 요소 만 포함하고 텍스트는 없습니다.
사용중인 스키마 (DTD 또는 XSD)가없는 경우 요소 컨텐츠 기본값이 혼합되어 있으므로이 매개 변수는 결코 영향을 미치지 않습니다. (파서가 비표준 DOM 확장을 제공하지 않는 한 모든 알려지지 않은 요소를 포함하는 요소 컨텐츠로 취급하는 경우, Java에 사용할 수있는 것들이 아는 한).
예를 들어 <! doctype ... [...]> 선언에 내부 서브 세트를 추가하여 스키마 정보를 포함시키기 위해 파서로가는 도중에 문서를 해킹 할 수 있습니다. 무시하십시오 .ContentWhitespace 매개 변수를 사용하십시오.
또는 더 쉽게, 당신은 우편 처리 또는 lsparserfilter를 사용하는 것에 따라 공백 노드를 제거 할 수 있습니다.
다른 팁
이것은 (실제로) 늦은 답변이지만 여기에 내가 해결 한 방법은 다음과 같습니다. 나는 내 자신의 구현을 썼다 NodeList
수업. 그것은 단순히 비어있는 텍스트 노드를 무시합니다. 코드는 다음과 같습니다.
private static class NdLst implements NodeList, Iterable<Node> {
private List<Node> nodes;
public NdLst(NodeList list) {
nodes = new ArrayList<Node>();
for (int i = 0; i < list.getLength(); i++) {
if (!isWhitespaceNode(list.item(i))) {
nodes.add(list.item(i));
}
}
}
@Override
public Node item(int index) {
return nodes.get(index);
}
@Override
public int getLength() {
return nodes.size();
}
private static boolean isWhitespaceNode(Node n) {
if (n.getNodeType() == Node.TEXT_NODE) {
String val = n.getNodeValue();
return val.trim().length() == 0;
} else {
return false;
}
}
@Override
public Iterator<Node> iterator() {
return nodes.iterator();
}
}
그런 다음 모든 것을 감싸십시오 NodeList
이 클래스에서는 모든 공백 노드를 효과적으로 무시합니다. (0 길이의 트림 텍스트를 가진 텍스트 노드로 정의합니다.)
또한 각각의 고리에서 사용할 수 있다는 이점이 추가되었습니다.
나는 이것을함으로써 그것을 작동시켰다
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setIgnoringElementContentWhitespace(true);
dbFactory.setSchema(schema);
dbFactory.setNamespaceAware(true);
NodeList nodeList = element.getElementsByTagNameNS("*", "associate");
나는 lsparserfilter를 사용한다는 @bobince의 아이디어를 따랐다. 예, 인터페이스는 다음에 문서화되어 있습니다 https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/lsparserfilter.html 그러나 좋은 예/설명 자료를 찾기가 매우 어렵습니다. 상당한 검색 후 DOM 레벨 3로드 및 XML 참조 안내서를 찾았습니다. http://www.informit.com/articles/article.aspx?p=31297&seqnum=29 (Nicholas Chase, 2003 년 3 월 14 일). 그것은 저를 상당히 도왔습니다. 다음은 내 코드의 일부입니다.이 코드는 org.custommonkey.xmlunit으로 XML Diff를 수행합니다. (이것은 유료 작업을 도와주기 위해 내 시간에 쓰여진 도구이므로, 더 나은 예외 처리와 같은 많은 것들이 느려질 때를 남겼습니다.)
나는 특히 LSPARSERFILTER의 사용을 좋아합니다. 내 목적을 위해 ID 속성을 무시할 수있는 옵션을 추가 할 수 있기 때문에이 프레임 워크를 쉽게 향상시켜야합니다.
// A small portion of my main class.
// Other imports may be necessary...
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSParserFilter;
Document controlDoc = null;
Document testDoc = null;
try {
System.setProperty(DOMImplementationRegistry.PROPERTY, "org.apache.xerces.dom.DOMImplementationSourceImpl");
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
LSParser builder = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
LSParserFilter filter = new InputFilter();
builder.setFilter(filter);
controlDoc = builder.parseURI(files[0].getPath());
testDoc = builder.parseURI(files[1].getPath());
} catch (Exception exc) {
System.out.println(exc.getMessage());
}
//--------------------------------------
import org.w3c.dom.ls.LSParserFilter;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.NodeFilter;
public class InputFilter implements LSParserFilter {
public short acceptNode(Node node) {
if (Utils.isNewline(node)) {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
public int getWhatToShow() {
return NodeFilter.SHOW_ALL;
}
public short startElement(Element elem) {
return LSParserFilter.FILTER_ACCEPT;
}
}
//-------------------------------------
// From my Utils.java:
public static boolean isNewline(Node node) {
return (node.getNodeType() == Node.TEXT_NODE) && node.getTextContent().equals("\n");
}
이 시도:
private static Document prepareXML(String param) throws ParserConfigurationException, SAXException, IOException {
param = param.replaceAll(">\\s+<", "><").trim();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource in = new InputSource(new StringReader(param));
return builder.parse(in);
}