2017-06-14 42 views
0

我需要使用sax解析器從下面的xml中將所有xml元素(在特定元素下)作爲字符串。使用SAX解析器,需要所有xml元素(在特定元素下)作爲字符串

示例XML:

<root> 
    <meta> 
    <elememtA>xx</elememtA> 
    </meta> 
<payload> 
    <parent> 
     <child1>a</child1> 
    </parent> 
    <parent> 
     <child1>b</child1> 
    </parent> 
    </payload> 
</root> 

SAX解析器實現:

public class UserHandler extends DefaultHandler { 
    @Override 
    public void startElement(String uri, 
    String localName, String qName, Attributes attributes) 
    throws SAXException { 
    if (qName.equalsIgnoreCase("payload")) { 
    //need all elements inside payload as string 
} 

例如,

我需要休耕輸出:

<parent><child1>a</child1></parent><parent><child2>b</child2></parent> 
+0

喜,以爲你的意思是:一個 b jeorfevre

+0

喜,我沒有讓你 – pradeep

+0

剛剛編輯帖子,第二個參數是 b jeorfevre

回答

1

這裏是工作的代碼。 你可以在輸出的底線看到你的結果。請享用。

輸出

2017-06-14 09:43:49 DEBUG SaxTest:94 - start document 
2017-06-14 09:43:49 DEBUG SaxTest:107 - START - - parent 
2017-06-14 09:43:49 DEBUG SaxTest:107 - START - - child1 
2017-06-14 09:43:49 DEBUG SaxTest:33 - STRING : a 
2017-06-14 09:43:49 DEBUG SaxTest:52 - END - - child1 
2017-06-14 09:43:49 DEBUG SaxTest:52 - END - - parent 
2017-06-14 09:43:49 DEBUG SaxTest:107 - START - - parent 
2017-06-14 09:43:49 DEBUG SaxTest:107 - START - - child1 
2017-06-14 09:43:49 DEBUG SaxTest:33 - STRING : b 
2017-06-14 09:43:49 DEBUG SaxTest:52 - END - - child1 
2017-06-14 09:43:49 DEBUG SaxTest:52 - END - - parent 
2017-06-14 09:43:49 DEBUG SaxTest:41 - end document 
2017-06-14 09:43:49 INFO SaxTest:148 - RESULT 
<parent><child1>a</child1></parent><parent><child1>b</child1></parent> 

代碼JUnit中 - 與工作測試

package com.rizze.beans.labs.sof; 

import java.io.IOException; 
import java.io.StringReader; 

import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.parsers.SAXParserFactory; 

import org.junit.Test; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.xml.sax.Attributes; 
import org.xml.sax.ContentHandler; 
import org.xml.sax.InputSource; 
import org.xml.sax.Locator; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 

public class SaxTest { 

    public static Logger logger = LoggerFactory.getLogger(SaxTest.class); 


    public class SaxProcess implements ContentHandler { 

     private boolean start= false; 
     private static final String START_ITEM = "payload"; 
     private String result = ""; 

     @Override 
     public void characters(char[] ch, int begin, int length) throws SAXException { 
      if(start == true){ 
       logger.debug("STRING : "+new String(ch).substring(begin,begin+length)); 

       result+=new String(new String(ch).substring(begin,begin+length)); 
      } 
     } 

     @Override 
     public void endDocument() throws SAXException { 
         logger.debug("end document"); 
     } 

     @Override 
     public void endElement(String uri, String localName, String name) throws SAXException { 

      if(name!=null && name.compareToIgnoreCase(START_ITEM)==0){ 
       start = false; 
      } 
      else{ 
       if(start == true){ 
        logger.debug("END - "+ localName + " - " + name); 
        result+="</"+name+">"; 
       } 
      } 


     } 

     @Override 
     public void endPrefixMapping(String prefix) throws SAXException { 



     } 

     @Override 
     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { 

     } 

     @Override 
     public void processingInstruction(String target, String data) throws SAXException { 


     } 

     @Override 
     public void setDocumentLocator(Locator locator) { 

     } 

     @Override 
     public void skippedEntity(String name) throws SAXException { 


     } 

     @Override 
     public void startDocument() throws SAXException { 
      start=false; 
      result = ""; 

      logger.debug("start document"); 
     } 

     @Override 
     public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException { 

      if(name!=null && name.compareToIgnoreCase(START_ITEM)==0){ 
       start = true; 
      } 
      else{ 

       if(start == true){ 
        //if already started ... go on 
        logger.debug("START - "+ localName + " - " + name); 
        result+="<"+name+">"; 
       } 
      } 


     } 

     @Override 
     public void startPrefixMapping(String prefix, String uri) throws SAXException { 


     } 

     /** 
     * return resulting string 
     * @return 
     */ 
     public String getResult(){ 
      return result; 
     } 

    } 





    @Test 
    public void test() { 


     String xml = "<root><meta><elememtA>xx</elememtA></meta><payload><parent><child1>a</child1></parent><parent><child1>b</child1></parent></payload></root>"; 
     InputSource in = new InputSource(new StringReader(xml)); 


      try { 
       XMLReader reader= SAXParserFactory.newInstance().newSAXParser().getXMLReader(); 
       SaxProcess p=new SaxProcess(); 
       reader.setContentHandler(p); 
       reader.parse(in); 
       logger.info("RESULT \n"+p.getResult()); 
      } catch (ParserConfigurationException | SAXException | IOException e) { 
       e.printStackTrace(); 
      } 

    } 

} 
+0

哇這麼多的代碼! – SomeDude

+0

@svasa =>問題是如何在SAX中使用ContentHandler。這段代碼對這個問題作出了迴應,並且也在單個文件中工作。如果您取消日誌記錄/導入....,您將減少50%的代碼大小。 – jeorfevre

0

看來你需要一個輸出i n xml形式,即。您需要xml格式的parent節點。 SAXParser或XPath引擎適用於節點和節點名稱。您必須編寫特殊代碼才能將所需的輸出作爲xml返回,這可能非常麻煩並且難以維護。

輕鬆獲得所需輸出xml的一種方法是使用XSLT。

考慮使用XSLT:在一個名爲parentxslt.xml文件

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" omit-xml-declaration="yes"/> 
<xsl:template match="/"> 
    <xsl:copy-of select="//payload/parent"/> 
</xsl:template> 
</xsl:stylesheet> 

地方這一點,並把你的輸入XML在parent.xml,那麼你可以使用下面的Java代碼:

try 
{ 
    File stylesheet = new File("parentxslt.xml"); 
    Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(stylesheet)); 
    StreamSource xmlSource = new StreamSource(new File("parent.xml")); 
    StringWriter sw = new StringWriter(); 
    transformer.transform(xmlSource, new StreamResult(sw)); 

    System.out.println(sw.toString().replaceAll("\\\r\\n\\s*", "")); 

} 
catch (Exception ex) 
{ 
    ex.printStackTrace(); 
} 
+0

不要僅僅因爲要對其進行轉換而創建DOM。向變壓器提供StreamSource或SAXSource要好得多。 –

+0

@MichaelKay感謝您的評論!我更新了我的代碼以使用'StreamSource' – SomeDude

+0

另外,爲什麼不把它縮小到''? –