2010-02-16 7 views
4

웹을 검색하여 stackoverflow를 위아래로 검색했습니다. 해결책 없음. 순수한 xslt here 내에서이 작업을 수행하는 방법을 찾았지만.다수의 큰 xml 파일을 하나로 효율적으로 병합

그러나 문제는 결과로 나오는 XML이 수백 MB의 크기가된다는 것입니다. 그래서 자바에서 SAX를 사용해야합니다. (제 xslt 솔루션, xslt ;-)로 태그를 달았음에도 불구하고)

자세히 설명해 드리겠습니다. 필자는 여러 개의 xml 파일 (선호되는 InputSteam)을 파싱해야합니다. XML를 결과

<root> 
    <doc> 
    <tag>test1</tag> 
    </doc> 
    <doc> 
    <tag>test2</tag> 
    </doc> 
    ... 
</root> 

<root> 
    <doc> 
    <tag>test3</tag> 
    </doc> 
    <doc> 
    <tag>test4</tag> 
    </doc> 
    ... 
</root> 

inputstream1 + inputstream2 + ... + inputstreamN =

inputstream2 inputstream1

같은 파일 또는의 InputStream의 모습. 모양은 다음과 같습니다

<root> 
    <doc> 
    <tag>test1</tag> 
    </doc> 
    <doc> 
    <tag>test2</tag> 
    </doc> 
    ... 
    <doc> 
    <tag>test3</tag> 
    </doc> 
    <doc> 
    <tag>test4</tag> 
    </doc> 
    ... 
</root> 

누군가가 해결책이나 링크가 있습니까? 사용자 지정 InputSource를 구현하여이 작업을 수행 할 수 있습니까? 아니면 사용자 지정 ContentHandler를 사용해야합니까? 아니면 joost/stx으로 가능합니까?

좋은 점은 ContentHandler를 사용할 수 있다는 것이 약간의 변형을 적용 할 수 있다는 것입니다 (이미 구현했습니다).

XMLReader xmlReader = XMLReaderFactory.createXMLReader(); 
xmlReader.setContentHandler(customHandler); 
xmlReader.parse(getInputSource()); // only one InputStream possible 

또는 내의 ContentHandler 내에서 직접에는 InputStream을 구문 분석해야하지만 문제는 내가 InputSource의 여러개의 파일이나의 InputStream의를 통과 할 수있는 방법을 모르겠입니다?

답변

0

에서 그것을 얻을 수 있다면 나는 마지막으로 다음 코드를 통해이 관리 :

finalHandler = new StreamResult(new OutputStreamWriter(System.out)); 
    // customHandler extends DefaultHandler 
    CustomTransformerHandler customHandler = new CustomTransformerHandler(
     finalHandler); 
    customHandler.startDocumentExplicitly(); 
    InputStream is = null; 
    while ((is = customHandler.createNextInputStream()) != null) { 
    // multiple inputStream parsing 
    XMLReader myReader = XMLReaderFactory.createXMLReader(); 
    myReader.setContentHandler(customHandler); 
    myReader.parse(new InputSource(is)); 
    } 
    customHandler.endDocumentExplicitly(); 

중요한 부분은 비어 있으며, StartDocument 및로부터 endDocument 방법을 떠나야했다. 다른 모든 메소드 (문자, startElement, endElement)는 finalHandler로 리디렉션됩니다. customHandler.createNextInputStream 메소드는 모든 입력 스트림을 읽을 경우 null을 리턴합니다.

1

Saxon의 유료 버전을 살펴볼 수 있습니다. 그것은 메모리에서 전체 DOM을 필요로하지 않는 on-the-fly XSLT를 처리 할 수 ​​있습니다.

+0

음, xslt에서는 사용자가 어디에 있든 관계없이 첫 번째 노드와 마지막 노드를 조회 할 수 있습니다. 즉 : 모든 것이 기억 속에 있어야합니다 ... xslt의 정의에 따라. 아니면 어떻게 생각하니? – Karussell

+0

상당히 큰 XSLT 프로그램의 하위 세트가 있습니다. 실행하기 위해 메모리에 전체 DOM 트리가 필요하지 않습니다. –

+0

아, 감사합니다. 이제 나는 – Karussell

2

필자는이 작업을 직접 해보지는 않았지만, IBM developerworks 기사를 보았습니다.

은 지금은 조금 오래된,하지만이 대신 SAX의 경우 StAX입니다 http://www.ibm.com/developerworks/xml/library/x-tipstx5/index.html

보십시오. 현재 JDK에 StAX가 포함되어 있는지 잘 모르겠습니다. 하지 당신은 아마 http://stax.codehaus.org/

+0

링크를 이용해 주셔서 감사합니다. 나는 이것을 조사 할 것이다! – Karussell

+0

+1 JDK에는 1.5에서부터 StAX가 포함되어 있습니다. SAX보다 훨씬 편리하게 사용할 수 있습니다. – helpermethod

0

파일을 병합하는 가장 효과적인 방법은 VTD-XML, AFAIK에서 제공하는 바이트 수준 잘라 내기 및 붙여 넣기 기능을 사용하는 것입니다. 두 파일을 모두 가져 와서 VTDNav 객체로 구문 분석 한 다음 XMLModifier 객체를 인스턴스화하고 두 번째 파일에서 단편을 가져온 다음 첫 번째 파일에 삽입합니다. SAX보다 훨씬 효율적입니다. 결과 XML 파일에 쓰여진 방향을 얻습니다. 메모리에 저장할 필요가 없습니다. 아래는 20 줄 미만의 완전한 코드입니다 ...

import com.ximpleware.*; 
import java.io.*; 

public class merge { 
    // merge second.xml into first.xml assuming the same encoding 
    public static void main(String[] s) throws VTDException, IOException{ 
     VTDGen vg = new VTDGen(); 
     if (!vg.parseFile("d:\\xml\\first.xml", false)) 
      return; 
     VTDNav vn1=vg.getNav(); 
     if(!vg.parseFile("d:\\xml\\second.xml", false)) 
      return; 
     VTDNav vn2 = vg.getNav(); 
     XMLModifier xm = new XMLModifier(vn1); 
     long l = vn2.getContentFragment(); 
     xm.insertBeforeTail(vn2, l); 
     xm.output("d:\\xml\\merged.xml"); 
    } 
} 
+0

흠.하지만 기억에 남기고 싶지는 않습니다. 직접 디스크에 직접 연결하십시오. 그리고 그게 어떻게 색소폰보다 더 빨리 될지 이해하지 못합니다. – Karussell

+0

색소폰을 사용하면 디스크에 파이핑하는 것 이상으로 SAX의 오버 헤드를 파싱하는 것이 VTD-XML을 사용하여 전체 낭비입니다. 필자는 10 배 (적어도) 성능을 보지 않을 것입니다. 개선 ... –

+0

좋습니다. vtd-xml 힌트를 보내 주셔서 감사합니다. 그것은 유망 해 보입니다 (내가 sourceforge 웹 사이트에서 읽을 수있는 것). 그러나 그것은 100 배 더 빠를지라도. doc (또는 그 이상)을 100 % RAM으로 사용하면 사용할 수 없습니다 : 결과 XML이 메모리에도 들어 가지 않을 수 있습니다. – Karussell

관련 문제