Как игнорировать пробелы при чтении файла для создания XML DOM

Я пытаюсь прочитать файл для создания документа DOM, но в файле есть пробелы и новые строки, и я пытаюсь игнорировать их, но я не мог:

DocumentBuilderFactory docfactory=DocumentBuilderFactory.newInstance();
docfactory.setIgnoringElementContentWhitespace(true);

Я вижу в Javadoc, что метод setIgnoringElementContentWhitespace работает только тогда, когда флаг проверки включен, но у меня нет схемы DTD или XML для документа.

что я могу сделать?

обновление

мне не нравится идея представиться форуме указано Tomalak, но это не работает, я использовал java 1.6 в среде linux. Я думаю, что если больше не предлагается, я сделаю несколько методов для игнорирования текстовых узлов пробелов

5 ответов


'IgnoringElementContentWhitespace' не об удалении все чисто-пробелы текстовые узлы, только пробелы узлы, чьи родители описаны в схеме как имеющие содержание элемента - то есть, они содержат только другие элементы и никогда текст.

Если вы не используете схему (DTD или XSD), содержимое элемента по умолчанию смешивается, поэтому этот параметр никогда не будет иметь никакого эффекта. (Если синтаксический анализатор не предоставляет нестандартное расширение DOM для обработки всех неизвестных элементы, содержащие содержимое элемента, которое, насколько я знаю, недоступно для Java.)

вы можете взломать документ по пути в парсер, чтобы включить информацию о схеме, например, добавив внутреннее подмножество к декларация, содержащая объявления, затем используйте параметр IgnoringElementContentWhitespace.

или, возможно, проще, вы можете просто удалить узлы пробелов, либо в постпроцесс, или как они приходят с помощью 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();
    }
}

затем обернуть все ваши NodeLists в этом классе, и он будет эффективно игнорировать все узлы пробелов. (Который я определяю как текстовые узлы с обрезанным текстом 0-длины.)

оно также имеет добавленное преимущество мочь быть использованным в для-каждом цикле.


Я сделал это работает, делая это

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setIgnoringElementContentWhitespace(true);
        dbFactory.setSchema(schema);
        dbFactory.setNamespaceAware(true);
NodeList nodeList = element.getElementsByTagNameNS("*", "associate");

попробуйте это:

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

    }

Я закончил тем, что последовал идее @bobince об использовании LSParserFilter. Да, интерфейс задокументирован вhttps://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSParserFilter.html но очень трудно найти хороший пример / объяснение материала. После значительного поиска я нашел DOM Level 3 Load и Save XML Reference Guide на http://www.informit.com/articles/article.aspx?p=31297&seqNum=29 (Николас Чейз, 14 Марта 2003). Это мне очень помогло. Вот части моего кода, который делает XML diff с org.custommonkey.xmlunit. (Это инструмент, написанный в мое свободное время, чтобы помочь мне с оплачиваемой работой, поэтому я оставил много вещей, таких как лучшая обработка исключений, когда все медленно.)

мне особенно нравится использование 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");
    }