如何使用Java和Stax从Xml中删除元素及其子元素

3
我有一个包含以下数据的大文件:
<releases>
   <release>
   ......
      <companies>
         <company>
         </company>
      </companies>
   </release>
   <release>
   ......
</releases>

我希望能够生成一个与输入文件相同但删除了所有公司元素及其子元素的输出文件。我正在尝试使用Stax,我想它会遍历元素,然后如果我匹配到了某个元素,我就可以不写入那个元素,这样所在的部分就被删除了。比如说,如果我扔掉了“公司”元素,那么其中的“员工”和“产品”元素也会被删除,是这样吗?
例如:
<releases>
   <release>
   ......
   </release>
   <release>
   ......
</releases>

这是我目前的代码:
        XMLInputFactory  inputFactory = XMLInputFactory.newInstance();
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        InputStream in = new FileInputStream(source);
        XMLEventReader reader = inputFactory.createXMLEventReader(in);

        OutputStream out = new FileOutputStream(target);
        XMLEventWriter writer =  outputFactory.createXMLEventWriter(out);
        XMLEvent event;
        while(reader.hasNext()){
            event = reader.nextEvent();
            writer.add(event);
            if(event.getEventType() == XMLStreamConstants.START_ELEMENT)
            {
                if(event.asStartElement().getName().toString().equalsIgnoreCase("companies"))
                {
                    System.out.println("Deleting:"+event);
                    continue;
                }
                else
                {
                    writer.add(event);
                }
            }
            else
            {
                writer.add(event);
            } 
        }
1个回答

6

我想我现在明白了,Stax是逐个处理元素的,所以我需要标记何时找到起始元素,设置一个变量来指示所有后续数据应该被忽略,直到达到结束元素。

代码示例:

import javax.xml.stream.*;
import javax.xml.stream.events.XMLEvent;
import java.io.*;

public class FixDb
{

    public static void main(String[] args) throws Exception
    {
        File source = new File(args[0]);
        if(!source.exists())
        {
            System.out.println("File:"+source+ " does not exist");
        }

        File target = new File(source+".new");

        XMLInputFactory  inputFactory = XMLInputFactory.newInstance();
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        InputStream in = new FileInputStream(source);
        XMLEventReader reader = inputFactory.createXMLEventReader(in);

        OutputStream out = new FileOutputStream(target);
        XMLEventWriter writer =  outputFactory.createXMLEventWriter(out);
        XMLEvent event;

        boolean deleteSection = false;
        while(reader.hasNext())
        {
            event = reader.nextEvent();
            if(event.getEventType() == XMLStreamConstants.START_ELEMENT && event.asStartElement().getName().toString().equalsIgnoreCase("companies"))
            {
                deleteSection=true;
                continue;
            }
            else if(event.getEventType() == XMLStreamConstants.END_ELEMENT && (event.asEndElement().getName().toString().equalsIgnoreCase("companies")))
            {
                deleteSection=false;
                continue;
            }
            else if(deleteSection)
            {
                continue;
            }
            else
            {
                writer.add(event);
            }
        }
    }
}

只是一个小注释,代码对于像 <companies><companies></companies></companies> 这样的内容将无法工作,因为 deleteSection 将被设置在元素 #1 上,但在元素 #3 上却未被设置(而不是 #4)... - malat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接