Как фильтровать теги XML, а затем записывать отфильтрованные теги в динамически генерируемые файлы - PullRequest
2 голосов
/ 27 марта 2012

У меня есть этот код Java:

public static void main(String[] args) throws Exception {

    String filename = "testXML.xml";
    String fileOutputName = "output.xml";
    try
    {           
        XMLInputFactory xmlif = null;
        xmlif = XMLInputFactory.newInstance();
        xmlif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES,Boolean.TRUE);
        xmlif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,Boolean.FALSE);
        xmlif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE);
        xmlif.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
        xmlif.setProperty(XMLInputFactory.REPORTER,"");
        FileInputStream fis = new FileInputStream(filename);
        XMLStreamReader xmlr = xmlif.createFilteredReader(xmlif.createXMLStreamReader(fis),new xmlReader());            

        OutputStream outputFile = new FileOutputStream(fileOutputName);                     
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();            
        XMLStreamWriter xmlWriter = outputFactory.createXMLStreamWriter(outputFile);    

        while (xmlr.hasNext())          
        {               
            write(xmlr, xmlWriter);             
            xmlr.next();
        }
        //write(xmlr, xmlWriter);                                   
        xmlWriter.flush();
        xmlWriter.close();          
        xmlr.close();
        outputFile.close();         
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

public boolean accept(XMLStreamReader reader) {     
    filters logic
    return true;
}

public static void write(XMLStreamReader xmlr, XMLStreamWriter writer) throws XMLStreamException {
    switch (xmlr.getEventType()) {
    case XMLEvent.START_ELEMENT:            
        final String localName = xmlr.getLocalName();
        writer.writeStartElement(localName);    
    break;
    case XMLEvent.END_ELEMENT:          
        writer.writeEndElement();
    break;
    case XMLEvent.SPACE:
    break;
    case XMLEvent.CHARACTERS:           
        writer.writeCharacters(xmlr.getTextCharacters(), xmlr.getTextStart(), xmlr.getTextLength());                    
        break;
    case XMLEvent.PROCESSING_INSTRUCTION:           
        writer.writeProcessingInstruction(xmlr.getPITarget(), xmlr.getPIData());            
    break;
    case XMLEvent.CDATA:                
            writer.writeCData(xmlr.getText());              
    break;
    case XMLEvent.COMMENT:
        writer.writeComment(xmlr.getText());
    break;
    case XMLEvent.ENTITY_REFERENCE:
        writer.writeEntityRef(xmlr.getLocalName());
    break;
    case XMLEvent.START_DOCUMENT:           
        String encoding = xmlr.getCharacterEncodingScheme();
        String version = xmlr.getVersion();
        if (encoding != null && version != null)
            writer.writeStartDocument(encoding, version);
        else if (version != null)
            writer.writeStartDocument(xmlr.getVersion());               
    break;          
    case XMLEvent.END_DOCUMENT:         
        writer.writeEndDocument();          
    break;
    case XMLEvent.DTD:
        writer.writeDTD(xmlr.getText());            
    break;
    }
  }

, который анализирует XML следующим образом:

<xml>
<element id="1">
    <field>Some field</field>
    <field2>Some other field value</field2>
    <comment>This will be ignored, so whatever.</comment>
</element>
<element id="2">
    <field>Value for field 1</field>
    <field2>Value for field 2</field2>
    <comment>Blah, blah, blah</comment>
</element>
...
<element id="n">
    <field>Value for field n</field>
    <field2>Value for field n</field2>
    <comment>Comment may be as long as a politician speech</comment>
</element></xml>

В основном я фильтрую файл по тегам и записываю код в файл XML.

Теперь проблема в том, что я пытаюсь сделать что-то вроде этого:

while (xmlr.hasNext())          
        {
            XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(new FileOutputStream(currentFile));
            write(xmlWriter);
            xmlr.next();
            xmlWriter.close();
        }           
        xmlr.close();

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

Это исключение:

java.util.EmptyStackException
at com.bea.xml.stream.util.Stack.pop(Stack.java:XX)
at com.bea.xml.stream.XMLWriterBase.writeEndElement(XMLWriterBase.java:XX)
at xmlReader.write(xmlReader.java:XX)
at xmlReader.main(xmlReader.java:XX)

Кто-нибудь знает, как я могу это исправить?

Спасибо.

Обновление 1 Кто-нибудь знает, удаляет ли реализация XMLWriter все отправленные значения каждый раз, когда средство записи закрывается?

...