代码之家  ›  专栏  ›  技术社区  ›  Telcontar

如何在读取文件以生成XML DOM时忽略空白

  •  6
  • Telcontar  · 技术社区  · 16 年前

    我试图读取一个文件来生成一个DOM文档,但该文件有空白和换行符,我试图忽略它们,但我不能:

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

    我在JavaDoc中看到,setIgnoringElementContentWhitespace方法仅在启用验证标志时运行,但我没有文档的DTD或XML模式。

    我能做什么?

    更新

    我不喜欢自我介绍!元素…我尝试过 提出的解决方案 forum Tomalak指出,但它不起作用,我在Linux环境中使用了Java 1.6。我认为如果不再提出更多的方法,我将采取一些方法来忽略空白文本节点

    5 回复  |  直到 6 年前
        1
  •  10
  •   bobince    16 年前

    __ignoringElementContentWhitespace_ 全部的 纯空白文本节点,只有父节点在模式中描述为具有元素内容的空白节点,也就是说,它们只包含其他元素,而不包含文本。

    如果您没有使用模式(DTD或XSD),那么元素内容默认为mixed,因此此参数将不会有任何效果。(除非解析器提供非标准DOM扩展,以将所有未知元素视为包含元素内容,据我所知,Java可用的元素不包含这些元素内容。)

    您可以在进入解析器的过程中对文档进行黑客攻击,以包含模式信息,例如,通过向<添加内部子集!文档类型…[…]gt;声明包含<!元素…>声明,然后使用ignoringElementContentWhitespace参数。

    或者,可能更容易,您可以在后期处理中或者在使用lsparserfilter时除去空白节点。

        2
  •  5
  •   jjnguy Julien Chastang    13 年前

    这是一个(真的)迟来的答案,但这里是我如何解决的。我自己编写了一个 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();
        }
    }
    

    然后你把你所有的 NODLIST 在这个类中,它将有效地忽略所有空白节点。(我将其定义为具有0长度修剪文本的文本节点。)

    它还具有能够在for-each循环中使用的附加好处。

        3
  •  2
  •   huppyuy    11 年前

    我做这个使它起作用

    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            dbFactory.setIgnoringElementContentWhitespace(true);
            dbFactory.setSchema(schema);
            dbFactory.setNamespaceAware(true);
    NodeList nodeList = element.getElementsByTagNameNS("*", "associate");
    
        4
  •  1
  •   Tamias    6 年前

    我最终跟随@bobince使用lsparserfilter的想法。是的,接口记录在 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");
        }
    
        5
  •  0
  •   ImGroot    7 年前

    试试这个:

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