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

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

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

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

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

Обновление

Мне не нравится идея представить объявления mySelf <! ELEMENT ..., и я попробовал Решение, предложенное на форуме <a href="http://forums.sun.com/thread.jspa?messageID=2054303#2699961" rel="nofollow noreferrer"> 1011 *, на которое указывает Томалак, но оно не работает, я использовал Java 1.6 в среде Linux. Я думаю, что если больше ничего не будет предложено, я сделаю несколько методов, чтобы игнорировать пробельные текстовые узлы

Ответы [ 5 ]

10 голосов
/ 23 октября 2008

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

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

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

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

5 голосов
/ 02 мая 2011

Это (действительно) поздний ответ, но вот как я его решил. Я написал свою собственную реализацию класса 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).

Он также имеет дополнительное преимущество, заключающееся в возможности использования в цикле for-each.

2 голосов
/ 26 октября 2013

Я сделал это, сделав это

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setIgnoringElementContentWhitespace(true);
        dbFactory.setSchema(schema);
        dbFactory.setNamespaceAware(true);
NodeList nodeList = element.getElementsByTagNameNS("*", "associate");
1 голос
/ 07 июля 2018

В итоге я последовал идее @ bobince об использовании LSParserFilter. Да, интерфейс задокументирован на https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSParserFilter.html, но очень сложно найти хороший пример / пояснительный материал. После долгих поисков я нашел Справочное руководство по загрузке и сохранению XML DOM Level 3 по адресу http://www.informit.com/articles/article.aspx?p=31297&seqNum=29 (Николас Чейз, 14 марта 2003 г.). Это помогло мне значительно. Вот части моего кода, который выполняет различие XML с 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");
    }
0 голосов
/ 17 февраля 2018

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

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

    }
...