2012-12-12 3 views
4

Java 및 SAX 파서를 사용하여 XML 구문 분석을 처음 사용합니다. 정말 큰 XML 파일을 가지고 있기 때문에 크기 때문에 SAX 파서를 사용하는 것이 좋습니다. 내 작업의 일부분을 파싱하고 예상대로 작동합니다. 이제 XML 작업에는 사용자 요청에 따라 일부 노드 삭제/업데이트 작업이 하나 남았습니다.sax 및 java를 사용하여 xml 파일에서 여러 노드 제거

모든 태그를 이름으로 찾아서 data 속성 등을 변경할 수 있습니다. SAX로이를 수행 할 수 있다면 삭제도 가능할 수 있습니다.

샘플 XML은 일부 경우에 일부 기능을 설명합니다. 사용자 입력은 "사례"이름 (case1, case2)입니다. 사용자가 아니라 case1 태그 (예 : case1에 대한) 이러한 경우 중 하나를 삭제하고자 할 경우

<ruleset> 
    <rule id="1"> 
     <condition> 
      <case1>somefunctionality</case1> 
      <allow>true</allow> 
     </condition> 
    </rule> 
    <rule id="2"> 
     <condition> 
      <case2>somefunctionality</case2> 
      <allow>false</allow> 
     </condition> 
    </rule> 
</ruleset> 

는 전체 rule 태그는 삭제해야합니다. ,

<ruleset> 
    <rule id="2"> 
     <condition> 
      <case2>somefunctionality</case2> 
      <allow>false</allow> 
     </condition> 
    </rule> 
</ruleset> 

내 질문은이는 SAX를 사용하여 수행 할 수 있습니다 : case1이 삭제 될 경우, XML이 될 것인가? 이 시점에서 DOM이나 다른 파서를 사용할 수 없습니다. 다른 옵션은 문자열 검색뿐입니다. SaxParser를 사용하여 어떻게 수행 할 수 있습니까?

답변

5

한번에 출력

XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) { 
     private boolean skip; 

     @Override 
     public void startElement(String uri, String localName, String qName, Attributes atts) 
       throws SAXException { 
      if (qName.equals("rule")) { 
       if (atts.getValue("id").equals("1")) { 
        skip = true; 
       } else { 
        super.startElement(uri, localName, qName, atts); 
        skip = false; 
       } 
      } else { 
       if (!skip) { 
        super.startElement(uri, localName, qName, atts); 
       } 
      } 
     } 

     public void endElement(String uri, String localName, String qName) throws SAXException { 
      if (!skip) { 
       super.endElement(uri, localName, qName); 
      } 
     } 

     @Override 
     public void characters(char[] ch, int start, int length) throws SAXException { 
      if (!skip) { 
       super.characters(ch, start, length); 
      } 
     } 
    }; 
    Source src = new SAXSource(xr, new InputSource("test.xml")); 
    Result res = new StreamResult(System.out); 
    TransformerFactory.newInstance().newTransformer().transform(src, res); 

<?xml version="1.0" encoding="UTF-8"?><ruleset> 
    <rule id="2"> 
     <condition> 
      <case2>somefunctionality</case2> 
      <allow>false</allow> 
     </condition> 
    </rule> 
</ruleset> 
+0

이 항상 SAX 순차적 요소를 구문 분석으로 예상대로 작동하지 않습니다 - 당신은 서로 인접한 2 가까운 태그가있는 경우하는 endElement 방법이 될 것입니다 의미 두 번 호출되며 skip이 호출 된 마지막 시간 (마지막 startElement)에 따라 건너 뜁니다. – Mike

0

구성해야 할 것은 SAX 이벤트 버퍼입니다.

<rule> 요소가 올 경우, 해당 요소 (또는 재생성에 필요한 정보)와 삭제하려는 '사례'사이에 발생하는 다른 모든 이벤트를 저장해야합니다.

저장 한 '규칙'이 삭제해야 할 규칙과 같은 경우 정보를 버리고 계속하십시오.

저장 한 '규칙'이 삭제해야하는 것이 아닌 경우 저장 한 색소폰 이벤트를 재생성하고 계속 진행해야합니다.

0

SAX는 XML 읽기/구문 분석에 가장 일반적으로 사용됩니다. 그러나 SAX를 사용하여 파일을 쓰는 방법에 대한 기사가 있습니다. 기본적인 아이디어는 당신이

입니다

http://xmlwriter.net/sample_chapters/Professional_XML/31100604.shtml

[이 기사는 그래서 SAX의 이전 버전을 사용하고 날짜가 1999이지만, 개념은 여전히 ​​적용] - 그리고 그 장을 사용할 나타납니다 온라인 참조 커스텀 DocumentHandler/ContentHandler를 작성합니다. SAX 이벤트를받을 때마다 이벤트는 직렬화되어 스트림/파일/어떤 것으로 든 이벤트를 씁니다. 따라서 입력 문서를 색소 이벤트의 소스로 사용하고 이러한 이벤트를 XMLOutputter에 전달합니다.

어려운 부분은 XML 문서를 SAX 이벤트의 스트림으로 구문 분석하고 XMLOutputter를 구동하고 입력 파일의 정확한 사본을 생성 할 수있는 지점에 도달하고 있습니다. 일단 작업을하게되면 편집 논리로 이동하여 규칙을 읽고이를 사용하여 출력 파일을 수정할 수 있습니다.

DOM, JDOM, XSLT 등보다 많은 작업이 있지만 전체 문서를 메모리에 저장할 필요가 없기 때문에 상황에 도움이 될 수 있습니다.

관련 문제