2009-05-15 3 views
7

내 응용 프로그램에서 XML 파일의 일부를 다음과 같이 변경합니다.Java로 파싱 할 때 문서 요소 앞에 공백을 두는 방법은 무엇입니까?

<?xml version="1.0" encoding="UTF-8"?> 
<!-- $Id: version control yadda-yadda $ --> 

<myElement> 
... 

<myElement> 앞에 빈 줄을 적어 둡니다. 로드, 변경 및 저장 후 결과는 만족스럽지 않습니다.

<?xml version="1.0" encoding="UTF-8"?> 
<!-- $Id: version control yadda-yadda $ --><myElement> 
... 

주석과 문서 노드 사이의 공백 (하나의 줄 바꿈)이 DOM에 전혀 표시되지 않습니다. 다음 자체 포함 코드는 문제를 안정적으로 재현합니다.

String source = 
    "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<!-- foo -->\n<empty/>"; 
byte[] sourceBytes = source.getBytes("UTF-16"); 

DocumentBuilder builder = 
    DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
Document doc = 
    builder.parse(new ByteInputStream(sourceBytes, sourceBytes.length)); 

DOMImplementationLS domImplementation = 
    (DOMImplementationLS) doc.getImplementation(); 
LSSerializer lsSerializer = domImplementation.createLSSerializer(); 
System.out.println(lsSerializer.writeToString(doc)); 

// output: <?xml version="1.0" encoding="UTF-16"?>\n<!-- foo --><empty/> 

이 문제를 피하는 방법을 알고 있습니까? 본질적으로, 출력을 입력과 동일하게하고 싶습니다. (xml 선언은 DOM의 일부가 아니기 때문에 다시 생성된다는 것을 알고 있지만 여기서는 문제가 아닙니다.)

+1

"-><"의 첫 번째 발생을 찾고 두 개의 개행을 추가하는 사용자 정의 OutputStream 클래스를 사용하여 출력을 해킹하는 결과가 발생했습니다. 첫 번째 문서 하위 노드가 실제로 주석 인 경우에만이 스트림을 사용합니다. 아직 해킹이되었지만 적어도 깔끔하게 캡슐화 된 :-) –

+0

같은 문제가 있습니다. 도와주세요. http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

답변

2

근본 원인은 표준 DOM Level 3가 스펙을 파괴하지 않고 문서의 자식으로 텍스트 노드를 나타낼 수 없다는 것입니다. 공백은 호환되는 파서에 의해 삭제됩니다.

Document -- 
    Element (maximum of one), 
    ProcessingInstruction, 
    Comment, 
    DocumentType (maximum of one) 

표준 호환 솔루션이 필요하고 목표는 100 % 재생산이 아닌 가독성이라면 출력 메커니즘에서 찾아 볼 것입니다.

+0

좋은 답변이지만, 내 생각에이 사양에있는 어리석은 버그입니다. 문서 요소 앞에 텍스트를 확실히 출력 할 수는 있지만 입력 할 수는 없습니까? – Archie

+0

@McDowell 우리가 이것을 피하기 위해 할 수있는 일은 제 질문을 살펴보십시오. http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

1

일반적으로 XML에서 공백은 부적절한 것으로 간주되므로 XML 파일을 파싱 할 때 보존되지 않습니다. . XML을 출력하는 대부분의 라이브러리에는 멋진 서식 지정과 올바른 들여 쓰기로 출력하는 옵션이 있지만 항상 상당히 일반적입니다. 아니오 "여분의 행이 오른쪽에 있습니다 여기".

+1

요점은 원래 입력에 * 행이 있었고 모든 공백의 경우처럼 유지되어야한다는 것입니다. 문서의 나머지 부분에서! –

3

왜 이것을 피 하시겠습니까?

태그/요소 외부의 공백은 사양에 의해 중요하지 않은 것으로 정의됩니다. DOM이 나타내는 infoset에 관한 한, 존재하지 않습니다.

따라서 DOM을 다시 직렬화하면 거기에 없을 것입니다.

이 빈 줄에 의존하는 무언가를 개발하는 중이면 ...하지 마십시오.

+0

물론 어떤 프로그램도이 형식을 사용하지 않습니다. 그러나 파일에 번역 데이터가 포함되어 있습니다. 그들은 버전 관리에 체크인하고 지속적으로 유지 관리됩니다. 따라서 내 앱이 의도 한 변경 사항 만있는 경우 diff 파일을 보는 것이 좋습니다. –

+0

나는 그렇게 생각했다 ... 나는 그걸 다루는 유일한 방법은 파일에서이 빈 줄을 시작하는 것이 아니라고 생각한다. 나는이 라인을 유지할 수있는 추천 방법이 없다고 생각한다. 어쩌면 이러한 불일치를 피하기 위해 파일을 규칙적으로 정리 툴을 통과시켜야합니다. – Tomalak

+0

@Tomalak :: 도와주세요 : http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

6

동일한 문제가있었습니다. 내 솔루션은 내 자신의 XML 파서를 작성하는 것이 었습니다 : DecentXML

주요 기능 : 원래 입력, 공백, 엔터티, 모든 것을 100 % 보존 할 수 있습니다. 세부 사항을 신경 쓰지는 않지만 코드가 다음과 같이 XML을 생성해야하는 경우 :

<element 
    attr="some complex value" 
    /> 

다음을 수행 할 수 있습니다.

+0

제안 해 주셔서 감사합니다. DecentXML은 확실히 좋은 점을 염두에두고 있습니다. * bookmarksIt * "아직 또 다른 파서"프로젝트 중 적어도 하나가 실제로 존재할 좋은 이유가 있음을 알았습니다. 그러나 현재의 문제에 대해서는 처리 코드 전체에서 표준 DOM API를 유지하고 출력 단계에 선을 추가하는 것이 좋습니다. –

+0

그런 다음 루트 요소 앞에 수동으로 텍스트 노드를 추가해야합니다. Document 객체에서 일반 (비 요소) 노드를 추가하는 방법을 살펴보십시오. 이것이 가능하지 않다면 거기에 개행 문자를 해킹하는 작성자/출력 스트림에 대한 필터를 만들어야합니다. –

+0

@AaronDigulla ::이 질문에 나를 도울 수 있습니까? http://stackoverflow.com/questions/30940162/dom-parser-wrong-childnodes-count – user3930361

0

저는 Kris와 Tomalak에 동의합니다. 빈 줄은 XML 관점과 관련이 없습니다. 응용 프로그램에서 출력물에 빈 줄을 만들어야하는 경우 해당 요구 사항의 필요성을 검토하는 것이 좋습니다.

어쨌든 빈 줄을 표시하려면 사용중인 XML 파서의 소스 코드를 다운로드하고 해당 동작을 수정하는 것이 좋습니다. 그러나 표준 XML이 아니며 다른 응용 프로그램과 호환되지 않습니다.

+1

인간이 편집 할 수있는 XML 파일은 어떻습니까? 이 경우 원래 형식이 중요합니다. XML은 직렬화뿐만 아니라 바이너리 형식이라면 더 좋을 것입니다. – MarioVilas