XML dom을 생성하기 위해 파일을 읽는 동안 공백을 무시하는 방법

StackOverflow https://stackoverflow.com/questions/229310

  •  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);

    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top