Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用sax和java从xml文件中删除多个节点_Java_Xml_Sax - Fatal编程技术网

使用sax和java从xml文件中删除多个节点

使用sax和java从xml文件中删除多个节点,java,xml,sax,Java,Xml,Sax,我不熟悉使用Java和SAX解析器进行XML解析。我有一个非常大的XML文件,由于它的大小,有人建议我使用SAX解析器。我已经完成了对部分任务的解析,并且工作正常。现在,XML作业剩下一个任务:根据用户的请求删除/更新一些节点 我可以通过名称查找所有标记,更改它们的数据属性等。如果我可以使用SAX执行这些操作,那么也可以删除它们 示例XML描述了某些情况下的一些功能。用户输入的是“案例”名称(case1,case2) 我的问题是,这可以使用SAX来完成吗?我现在不能使用DOM或任何其他解析器。只

我不熟悉使用Java和SAX解析器进行XML解析。我有一个非常大的XML文件,由于它的大小,有人建议我使用SAX解析器。我已经完成了对部分任务的解析,并且工作正常。现在,XML作业剩下一个任务:根据用户的请求删除/更新一些节点

我可以通过名称查找所有标记,更改它们的
数据
属性等。如果我可以使用SAX执行这些操作,那么也可以删除它们

示例XML描述了某些情况下的一些功能。用户输入的是“案例”名称(
case1
case2


我的问题是,这可以使用SAX来完成吗?我现在不能使用DOM或任何其他解析器。只有另一个选项更糟糕:字符串搜索。如何使用SaxParser实现这一点?

您需要构造一个SAX事件缓冲区

当您访问
元素时,您需要保存该元素(或重新生成该元素所需的信息)以及它与要删除的“案例”之间发生的所有其他事件

如果您保存的“规则”与需要删除的规则相同,只需扔掉信息并继续


如果保存的“规则”不是需要删除的规则,则应重新生成已保存的sax事件并继续。sax最常用于读取/解析XML。但是有一篇文章介绍了如何使用SAX来编写文件。这一章似乎可以在网上找到——请参见:

[这篇文章的日期是1999年,所以它使用的是旧版本的SAX,但这些概念仍然适用]

基本思想是创建自定义DocumentHandler/ContentHandler。每当接收到SAX事件时,它都会序列化该事件并将其写入流/文件/任何内容。因此,您可以将输入文档用作sax事件的源,并将这些事件转发给XMLOutputter

最困难的部分是您可以将XML文档解析为SAX事件流,驱动XMLOutputer并生成输入文件的精确副本。一旦你开始工作,你就可以进入编辑逻辑,在那里你可以阅读你的规则并使用它们来修改输出文件

这比DOM、JDOM、XSLT等做的工作要多得多,但在您的情况下可能会有所帮助,因为您不必将整个文档存储在内存中

试试看

    XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {
        private boolean skip;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes atts)
                throws SAXException {
            if (qName.equals("rule")) {
                if (atts.getValue("id").equals("1")) {
                    skip = true;
                } else {
                    super.startElement(uri, localName, qName, atts);
                    skip = false;
                }
            } else {
                if (!skip) {
                    super.startElement(uri, localName, qName, atts);
                }
            }
        }

        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (!skip) {
                super.endElement(uri, localName, qName);
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (!skip) {
                super.characters(ch, start, length);
            }
        }
    };
    Source src = new SAXSource(xr, new InputSource("test.xml"));
    Result res = new StreamResult(System.out);
    TransformerFactory.newInstance().newTransformer().transform(src, res);
输出

<?xml version="1.0" encoding="UTF-8"?><ruleset>
    <rule id="2">
        <condition>
            <case2>somefunctionality</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>

某些功能
假的

当SAX按顺序解析元素时,这并不总是像预期的那样工作-这意味着如果有两个相邻的close标记,endElement方法将被调用两次,并将根据上次调用skip的时间(上次startElement)进行跳过
    XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {
        private boolean skip;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes atts)
                throws SAXException {
            if (qName.equals("rule")) {
                if (atts.getValue("id").equals("1")) {
                    skip = true;
                } else {
                    super.startElement(uri, localName, qName, atts);
                    skip = false;
                }
            } else {
                if (!skip) {
                    super.startElement(uri, localName, qName, atts);
                }
            }
        }

        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (!skip) {
                super.endElement(uri, localName, qName);
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (!skip) {
                super.characters(ch, start, length);
            }
        }
    };
    Source src = new SAXSource(xr, new InputSource("test.xml"));
    Result res = new StreamResult(System.out);
    TransformerFactory.newInstance().newTransformer().transform(src, res);
<?xml version="1.0" encoding="UTF-8"?><ruleset>
    <rule id="2">
        <condition>
            <case2>somefunctionality</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>