読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

SAXでXMLの複製を作る

Java

SAXTransformerFactory#newTransformerHandler() を使うと、SAXでXMLを読みつつそのコピーをストリームに書き出すことができます。委譲などを駆使してカスタマイズすれば、特定の要素を除いたXMLのコピーを作成するといったことも可能。DOMにしてからシリアライズするよりは高速でメモリ消費も少ないはず(たぶん)。以下は、コメントを除外したXMLのコピーを作成するサンプルです。

// XMLReaderを作る
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader r = factory.newSAXParser().getXMLReader();

// TransformerHandlerを作る
SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
final TransformerHandler h = stf.newTransformerHandler();

// コメントをフィルタするようにカスタマイズ。
TransformerHandler proxy = (TransformerHandler) Proxy.newProxyInstance(
    Thread.currentThread().getContextClassLoader(), 
    new Class[]{
        TransformerHandler.class, ContentHandler.class, DTDHandler.class, 
        LexicalHandler.class, DeclHandler.class}, 
    new InvocationHandler() {
        public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable {
            if ( "comment".equals( method.getName() )) {
                // コメントの場合は何もしない。
                return null;
            } else {
                return method.invoke(h, args);
            }
        }
    });

// 出力先の設定
// とりあえず標準出力に。
StreamResult result = new StreamResult(System.out);
h.setResult(result);

// XMLReaderに設定
r.setContentHandler( proxy );
r.setDTDHandler( proxy );
r.setProperty( "http://xml.org/sax/properties/lexical-handler", proxy );
r.setProperty( "http://xml.org/sax/properties/declaration-handler", proxy );

// パーズ
r.parse( new InputSource(ClassLoader.getSystemResourceAsStream("sax/test.xml")) );

次のようなXMLを対象として実行すると、

<?xml version="1.0" encoding="UTF-8" standalone='yes'?>
<!DOCTYPE test[
  <!ELEMENT hoge (#PCDATA|foo|var)*>
  <!ATTLIST hoge attr CDATA #REQUIRED>
]>
<hoge attr="test">

<?PI aaaaa ?>
<![CDATA[ CDATAsection ]]>

  <!-- comment -->
  <foo>foo</foo>
  <var>var</var>
</hoge>

以下の結果が出力されます。コメントとDTDがすっ飛ばされています。(JDKは1.5を使用)

<?xml version="1.0" encoding="UTF-8"?><hoge attr="test">

<?PI aaaaa ?>
<![CDATA[ CDATAsection ]]>

  
  <foo>foo</foo>
  <var>var</var>
</hoge>

Xalanの新しい奴(2.7.1で確認)をパスに通しておくと、DTDも出力されるようになります。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [
<!ELEMENT hoge (#PCDATA|foo|var)*>
<!ATTLIST hoge attr CDATA #REQUIRED>
]>
<hoge attr="test">

<?PI aaaaa ?>
<![CDATA[ CDATAsection ]]>

  
  <foo>foo</foo>
  <var>var</var>
</hoge>