Come ignorare gli spazi bianchi durante la lettura di un file per produrre un DOM XML

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

  •  04-07-2019
  •  | 
  •  

Domanda

Sto cercando di leggere un file per produrre un documento DOM, ma il file ha spazi bianchi e nuove righe e sto cercando di ignorarli, ma non sono riuscito:

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

Vedo in Javadoc che il metodo setIgnoringElementContentWhitespace funziona solo quando il flag di convalida è abilitato, ma non ho DTD o XML Schema per il documento.

Cosa posso fare?

:

Aggiornamento

Non mi piace l'idea di presentarmi < ! ELEMENT ... dichiarazioni e ho provato il soluzione proposta nel forum indicato da Tomalak, ma non lavoro, ho usato Java 1.6 in un ambiente Linux. Penso che se non verrà più proposto, farò alcuni metodi per ignorare i nodi di testo degli spazi bianchi

È stato utile?

Soluzione

&

# 8216; IgnoringElementContentWhitespace # 8217 &; non si tratta di rimuovere tutti nodi di testo in spazi bianchi, ma solo nodi di spazi bianchi i cui genitori sono descritti nello schema come aventi contenuto ELEMENT & # 8202; & # 8212; & # 8202; vale a dire, contengono solo altri elementi e mai testo.

Se non si utilizza uno schema (DTD o XSD), il contenuto dell'elemento viene impostato automaticamente su MISTO, quindi questo parametro non avrà alcun effetto. (A meno che il parser non fornisca un'estensione DOM non standard per trattare tutti gli elementi sconosciuti come contenenti contenuto ELEMENT, che per quanto ne so quelli disponibili per Java non lo fanno.)

È possibile hackerare il documento sulla strada nel parser per includere le informazioni sullo schema, ad esempio aggiungendo un sottoinsieme interno a < ! DOCTYPE ... [...] & Gt; dichiarazione contenente < ! ELEMENT ... & Gt; dichiarazioni, quindi utilizzare il parametro IgnoringElementContentWhitespace.

O, forse più facile, potresti semplicemente eliminare i nodi degli spazi bianchi, sia in un post-processo, sia quando arrivano usando un LSParserFilter.

Altri suggerimenti

Questa è una risposta (davvero) tardiva, ma ecco come l'ho risolta. Ho scritto la mia implementazione di una classe NodeList. Ignora semplicemente i nodi di testo vuoti. Il codice segue:

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

Quindi avvolgi tutti i tuoi <=> in questa classe e ignorerà efficacemente tutti i nodi degli spazi bianchi. (Che io definisco nodi di testo con testo ritagliato di lunghezza 0).

Ha anche l'ulteriore vantaggio di poter essere utilizzato in un ciclo for-each.

L'ho fatto funzionare facendo questo

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

Ho finito per seguire l'idea di @ bobince di usare un LSParserFilter. Sì, l'interfaccia è documentata su https : //docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSParserFilter.html ma è molto difficile trovare un buon esempio / materiale esplicativo. Dopo una ricerca approfondita, ho individuato la Guida di riferimento XML per il caricamento e il salvataggio di DOM livello 3 in http://www.informit.com/articles/article.aspx?p=31297 & amp; seqNum = 29 (Nicholas Chase, 14 marzo 2003). Questo mi ha aiutato considerevolmente. Ecco alcune parti del mio codice, che fa una diff XML con org.custommonkey.xmlunit. (Questo è uno strumento scritto sul mio tempo per aiutarmi con il lavoro retribuito, quindi ho lasciato molte cose, come una migliore gestione delle eccezioni, per quando le cose sono lente.)

Mi piace particolarmente l'uso di un LSParserFilter perché, per il mio scopo, probabilmente in futuro aggiungerò un'opzione per ignorare anche gli attributi ID, che dovrebbe essere un facile miglioramento con questo framework.

// 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");
    }

Prova questo:

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

    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top