如何让java XMLStreamReader能发出CDATA事件

要对一个带CDATA的XML文档的某些element内容加密,加密后除了被加密的element外,其他内容不能变。这个需求看起来比较简单,为了有比较好的性能,用了java XML stream API。先看看能否把一个XML文档由XMLStreamReader读出,再由XMLStreamWriter写入新的XML文件。代码比较简单:

import javax.xml.stream.*;
import java.io.StringWriter;
import java.io.FileReader;

public class XMLStreamWriterTest {
    public static void main(String...args ) throws Exception {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        XMLStreamReader streamReader = inputFactory.createXMLStreamReader( new FileReader( args[0] ) );

        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        StringWriter writer = new StringWriter();
        XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter( writer );
        StringBuilder content = new StringBuilder();

        while (streamReader.hasNext()) {
            switch( streamReader.next() ) {
                    case XMLStreamConstants.START_ELEMENT:
                        if( content.length() > 0 ) {
                            streamWriter.writeCharacters( content.toString() );
                        }
                        content.setLength( 0 );
                        streamWriter.writeStartElement( streamReader.getLocalName() );

                        //write the attribute
                        for( int i = 0, n = streamReader.getAttributeCount(); i < n; i++ ) {
                            streamWriter.writeAttribute(streamReader.getAttributeLocalName(i),streamReader.getAttributeValue(i));
                        }
                        break;
                    case XMLStreamConstants.END_ELEMENT:
                        if( content.length() > 0 ) {
                            streamWriter.writeCharacters( content.toString());
                            content.setLength(0);
                        }
                        streamWriter.writeEndElement();
                        break;
                    case XMLStreamConstants.SPACE:
                    case XMLStreamConstants.CHARACTERS:
                        content.append( streamReader.getText() );
                        break;
                    case XMLStreamConstants.CDATA:
                        streamWriter.writeCData( streamReader.getText());
                        break;
                    case XMLStreamConstants.ENTITY_REFERENCE:
                        streamWriter.writeEntityRef( streamReader.getText());
                        break;
                    case XMLStreamConstants.COMMENT:
                        streamWriter.writeComment( streamReader.getText());
                        break;
                    case XMLStreamConstants.DTD:
                        streamWriter.writeDTD( streamReader.getText());
                        break;
            }
        }
        System.out.println( writer );
    }
}

用文件Test1.xml测试一下,Test1.xml的内容如下:

<Element1>
    <Child1>this is first child</Child1>
    <Child2>this is second child</Child2>
</Element1>

$ java -cp . XMLStreamWriterTest Test1.xml

输出:

<Element1>
    <Child1>this is first child</Child1>
    <Child2>this is second child</Child2>
</Element1>

完全一样。

再用带CDATA的XML文件Test2.xml测试一下, Test2.xml的内容如下:

<Element1>
    <Child1>this is first child</Child1>
    <Child2><![CDATA[this is second child]]></Child2>
</Element1>

$ java -cp . XMLStreamWriterTest Test2.xml

输出:
<Element1>
    <Child1>this is first child</Child1>
    <Child2>this is second child</Child2>
</Element1>

给想要的结果不一样。怎么回事?上网查了一下,方法如下:

1) 需要将inputFactor中的属性javax.xml.stream.isCoalescing设置为false

2)需要将inputFactory中的属性"http://java.sun.com/xml/stream/properties/report-cdata-event"设置为true


修改代码:


import javax.xml.stream.*;
import java.io.StringWriter;
import java.io.FileReader;

public class XMLStreamWriterTest {
    public static void main(String...args ) throws Exception {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        inputFactory.setProperty( XMLInputFactory.IS_COALESCING,  Boolean.FALSE );
        inputFactory.setProperty( "http://java.sun.com/xml/stream/properties/report-cdata-event", Boolean.TRUE );
        XMLStreamReader streamReader = inputFactory.createXMLStreamReader( new FileReader( args[0] ) );

        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        StringWriter writer = new StringWriter();
        XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter( writer );
        StringBuilder content = new StringBuilder();

        while (streamReader.hasNext()) {
            switch( streamReader.next() ) {
                    case XMLStreamConstants.START_ELEMENT:
                        if( content.length() > 0 ) {
                            streamWriter.writeCharacters( content.toString() );
                        }
                        content.setLength( 0 );
                        streamWriter.writeStartElement( streamReader.getLocalName() );

                        //write the attribute
                        for( int i = 0, n = streamReader.getAttributeCount(); i < n; i++ ) {
                            streamWriter.writeAttribute(streamReader.getAttributeLocalName(i),streamReader.getAttributeValue(i));
                        }
                        break;
                    case XMLStreamConstants.END_ELEMENT:
                        if( content.length() > 0 ) {
                            streamWriter.writeCharacters( content.toString());
                            content.setLength(0);
                        }
                        streamWriter.writeEndElement();
                        break;
                    case XMLStreamConstants.SPACE:
                    case XMLStreamConstants.CHARACTERS:
                        content.append( streamReader.getText() );
                        break;
                    case XMLStreamConstants.CDATA:
                        streamWriter.writeCData( streamReader.getText());
                        break;
                    case XMLStreamConstants.ENTITY_REFERENCE:
                        streamWriter.writeEntityRef( streamReader.getText());
                        break;
                    case XMLStreamConstants.COMMENT:
                        streamWriter.writeComment( streamReader.getText());
                        break;
                    case XMLStreamConstants.DTD:
                        streamWriter.writeDTD( streamReader.getText());
                        break;
            }
        }
        System.out.println( writer );
    }
}



再运行一次:

$ java -cp . XMLStreamWriterTest Test2.xml

结果如下:

<Element1>
    <Child1>this is first child</Child1>
    <Child2><![CDATA[this is second child]]></Child2>
</Element1>


结果符合预期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值