문제

나는 dom4j를 사용하여 한 번에 스트림에서 단일 XML 문서를 읽고, 그것을 처리 한 다음 스트림의 다음 문서로 진행하려고합니다. 불행히도, DOM4J의 색소폰서 (표지 아래에서 JAXP 사용)는 다음 문서 요소를 계속 읽고 질식시킵니다.

문서 요소의 끝을 찾으면 SaxReader가 스트림 읽기를 중단하는 방법이 있습니까? 이것을 달성하는 더 좋은 방법이 있습니까?

도움이 되었습니까?

해결책

나는 이것을 일부 내부 JAXP 수업을 사용하여 일부 체조와 협력 할 수있었습니다.

  • xmlnsdocumentscannerimpl의 서브 클래스 인 사용자 정의 스캐너를 만듭니다
    • 명확한 드라이버, xmlnsdocumentscannerimpl.driver의 구현, 명확한 스캐너 내부에서 선언이나 요소가 표시 될 때 END_DOCUMENT를 반환합니다. FelementsCanner.getCurrentity ()에서 스캔을 받으십시오. 엔티티에 푸시 백 리더가있는 경우 엔티티 버퍼의 나머지 읽지 않은 문자를 리더로 밀어 넣으십시오.
    • 생성자에서 ftrailingmiscdriver를이 사용자 정의 드라이버의 인스턴스로 대체하십시오.
  • xincludeawareparserconfiguration의 서브 클래스 인 사용자 정의 구성 클래스를 만듭니다. STOCK_SCANNER를 생성자 의이 사용자 정의 스캐너 인스턴스로 대체합니다.
  • 이 사용자 정의 구성 클래스의 인스턴스를 "com.sun.org.apache.xerces.internal.xni.parser.xmlparserconfiguration"속성으로 설치하여 Dom4J의 SaxReader 클래스가 JAXP XMLREDER를 만들려고 할 때 인스턴스화됩니다.
  • 독자를 Dom4J의 SaxReader.Read () 메소드로 전달할 때는 1 차 차이터 기본값보다 훨씬 큰 버퍼 크기의 푸시 백 리더를 제공하십시오. JAXP의 APACHE2 사본 내부의 XmlentityManager의 기본 버퍼 크기를 지원하기에 최소 8192가 충분해야합니다.

내부 jaxp 클래스를 서브 클래스하는 것이 포함되어 있기 때문에 가장 깨끗한 솔루션은 아니지만 작동합니다.

다른 팁

아마도 같은 스트림에 동시에 둘 이상의 문서를 갖고 싶지 않을 것입니다. SaxReader가 첫 번째 문서의 끝에 도착할 때 멈출만큼 똑똑하다고 생각하지 않습니다. 이와 같은 스트림에 여러 문서가 필요한 이유는 무엇입니까?

스트림을 감싸고 다음 문서의 시작을 볼 때 파일의 끝을 반환 할 수있는 어댑터를 추가해야한다고 생각합니다. 내가 아는 한, 쓰여진 파서는 파일 끝이나 오류가 발생할 때까지 진행됩니다 ... <?xml version="1.0"?> 확실히 오류 일 것입니다.

처음에 문서를 스트림에 배치 할 책임이 있다고 가정하면 문서를 어떤 방식으로 쉽게 구분할 수 있어야합니다. 예를 들어:

// Any value that is invalid for an XML character will do.
static final char DOC_TERMINATOR=4;

BOOL addDocumentToStream(BufferedWriter streamOut, char xmlData[])
{
  streamOut.write(xmlData);
  streamOut.write(DOC_TERMINATOR);
}

그런 다음 스트림에서 읽을 때 Doc_terminator가 발생할 때까지 배열로 읽습니다.

char *getNextDocuument(BufferedReader streamIn)
{
  StringBuffer buffer = new StringBuffer();
  int character;

  while (true)
  {
    character = streamIn.read();
    if (character == DOC_TERMINATOR)
      break;

    buffer.append(character);
  }
  return buffer.toString().toCharArray();
}

4는 유효하지 않은 문자 값이므로 명시 적으로 추가하는 곳을 제외하고는 발생하지 않습니다. 따라서 문서를 분할 할 수 있습니다. 이제 SAX에 입력 할 수있는 결과 숯 배열을 감싸십시오.

...
  XMLReader xmlReader = XMLReaderFactory.createXMLReader();
...
  while (true)
  {
    char xmlDoc = getNextDocument(streamIn);

    if (xmlDoc.length == 0)
      break;

    InputSource saxInputSource = new InputSource(new CharArrayReader(xmlDoc));
    xmlReader.parse(saxInputSource);
  }
...

루프는 길이 0의 문서를 얻을 때 종료됩니다. 이는 GetNextDocument ()에서 스트림의 끝을 감지하기 위해 무언가를 추가 해야하는 마지막 문서를 추가 한 후 두 번째 doc_terminator를 추가해야 함을 의미합니다.

나는 매우 간단한 구문 분석 기능을 가진 내 자신의 창조물을 다른 독자로 기본 독자에게 래퍼함으로써 이것을하기 전에 이것을 해냈습니다. 문서의 닫는 태그를 알고 있다고 가정하면 래퍼는 단순히 일치를 위해 구문 분석합니다.u003C/MyDocument> ". EOF를 반환하는 것을 감지 할 때. 첫 번째 오프닝 태그를 구문 분석하고 일치하는 마감 태그에서 EOF를 반환하여 래퍼를 적응시킬 수 있습니다. 문서가 없기 때문에 마감 태그의 레벨을 실제로 감지 할 필요가 없다는 것을 알았습니다. 문서 태그 자체를 사용 했으므로 결산 태그의 첫 번째 발생이 문서를 종료했음을 보장했습니다.

내가 기억 하듯이, 트릭 중 하나는 DOM 리더가 입력 소스를 닫으므로 래퍼 블록을 Close ()하도록하는 것이 었습니다.

따라서 독자 입력이 주어지면 코드가 있습니다 ~할 것 같다 모양 :

SubdocReader sdr=new SubdocReader(input);
while(!sdr.eof()) {
    sdr.next();
    // read doc here using DOM
    // then process document
    }
input.close();

eof가 발생하면 eof () 메소드가 true를 반환합니다. 다음 () 메소드는 독자가 read ()에 대해 -1 리턴을 중지하도록 표시합니다.

바라건대 이것은 유용한 방향으로 당신을 가리 킵니다.

-- 키위.

입력 스트림을 내부 버퍼로 읽었습니다. 예상되는 총 스트림 크기에 따라 전체 스트림을 읽은 다음 하나의 XML과 다음 사이의 경계를 감지합니다 (찾아보십시오.

그런 다음 하나의 XML로 스트림을 처리하고 여러 XML이있는 스트림의 유일한 차이점은 버퍼 및 분할 로직입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top