2013-02-22 104 views
1

我的程序的概念是解析可以描述XML流內一組類的XML文件。每個類顯然可以有幾個方法和幾個屬性。這些方法又可以有幾個參數。使用SAX解析器解析嵌套的XML標記可能有重複。 Java

下面是XML文件的一個例子:

<stream> 
<class package="Mainpack" name="Person" visibility="public" alias="Aaron" type="class" spot="C"> 
    <property name="id" type="String" visibility="public"></property> 
    <property name="name" type="String" visibility="public"></property> 
    <method name="setID" return="void" visibility="public"> 
    <parameter name="name" type="string"> </parameter> 
    </method> 
    <method name="getID" return="String" visibility="public"></method> 
</class> 
</stream> 

每個元素(流,類等)具有與吸氣劑,setter和一個空的構造描述了它的類。該流包含一個類的列表。類包含名稱,包等的屬性,以及方法和參數(它們是獨立的類)的列表。我不會包含這些,因爲我認爲它們很簡單。

這是我寫的XMLHandler類:

public class XMLHandler extends DefaultHandler { 

Boolean currentElement = false; 
String currentValue = null; 

public static XMLStream xmlStream; 

    public XMLClass xmlClass = null; 
    public XMLMethod xmlMethod = null; 
    public XMLProperty xmlProperty = null; 
    public XMLParameter xmlParameter = null; 

@Override 
public void startElement(String uri, String localName, String qName, 
     Attributes attributes) throws SAXException { 
    currentElement = true; 

    switch (localName) { 
     case "stream": 
      { 
       xmlStream = new XMLStream(); 
      } 
     case "class": 
      { 
       /** Start and get attribute values */ 
       xmlClass = new XMLClass(); 
       String attr = attributes.getValue("package"); 
       xmlClass.setPackageName(attr); 
       attr = attributes.getValue("name"); 
       xmlClass.setClassName(attr); 
       attr = attributes.getValue("visibility"); 
       xmlClass.setVisibility(attr); 
       attr = attributes.getValue("alias"); 
       xmlClass.setAlias(attr); 
       attr = attributes.getValue("type"); 
       xmlClass.setType(attr); 
       attr = attributes.getValue("spot"); 
       xmlClass.setSpot(attr.charAt(0)); 
       break; 
      } 
     case "method": 
      { 
       xmlMethod = new XMLMethod(); 
       String attr = attributes.getValue("name"); 
       xmlMethod.setName(attr); 
       attr = attributes.getValue("return"); 
       xmlMethod.setReturnType(attr); 
       attr = attributes.getValue("visibility"); 
       xmlMethod.setVisibility(attr); 
       xmlClass.addMethod(xmlMethod); 
       break; 
      } 
     case "property": 
      { 
       xmlProperty = new XMLProperty(); 
       String attr = attributes.getValue("name"); 
       xmlProperty.setName(attr); 
       attr = attributes.getValue("type"); 
       xmlProperty.setType(attr); 
       attr = attributes.getValue("visibility"); 
       xmlProperty.setVisibility(attr); 
       xmlClass.addProperty(xmlProperty); 
       break; 
      } 
     case "parameter": 
      { 
       xmlParameter = new XMLParameter(); 
       String attr = attributes.getValue("name"); 
       xmlParameter.setName(attr); 
       attr = attributes.getValue("type"); 
       xmlParameter.setType(attr); 
       xmlMethod.addParameter(xmlParameter); 
       break; 
      } 
     } 
} 

/** Called when tag closing (ex:- <name>AndroidPeople</name> 
* -- </name>)*/ 
@Override 
public void endElement(String uri, String localName, String qName) 
     throws SAXException { 

    currentElement = false; 

      if (localName.equalsIgnoreCase("class")) 
       xmlStream.addClass(xmlClass); 
      else if (localName.equalsIgnoreCase("method")) 
       xmlClass.addMethod(xmlMethod); 
      else if (localName.equalsIgnoreCase("property")) 
       xmlClass.addProperty(xmlProperty); 
      else if (localName.equalsIgnoreCase("parameter")) 
       xmlMethod.addParameter(xmlParameter); 
} 

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

    if (currentElement) { 
     currentValue = new String(ch, start, length); 
     currentElement = false; 
    } 

} 

} 

我希望的邏輯是正確的。解析器在遇到流標記並設置屬性時創建一個Stream實例。在遇到班級標記時,​​它也是一樣。在類的結束標記上,類實例被添加到流的類列表中。對於與類有關的方法和屬性以及與方法有關的參數,這種行爲會重複。

我測試在Windows應用程序分析器,但你可以使用這種方法:

public static void main(String[]args) 
{ 
    try { 

     String xmlst = "<stream>\n<class package=\"Mainpack\" name=\"Person\" " 
       + "visibility=\"public\" alias=\"Aaron\" type=\"class\" spot=\"C\">\n " 
       + " <property name=\"id\" type=\"String\" visibility=\"public\"></property>\n " 
       + " <method name=\"getID\" return=\"void\" visibility=\"public\">\n\t<parameter name=\"name\" type=\"string\">" 
       + " </parameter>\n </method>\n</class>\n</stream>"; 

     SAXParserFactory spf = SAXParserFactory.newInstance(); 
     SAXParser sp = spf.newSAXParser(); 
     XMLReader xr = sp.getXMLReader(); 
     XMLHandler xh = new XMLHandler(); 

     InputSource is = new InputSource(); 
     is.setCharacterStream(new StringReader(xmlst)); 
     xr.setContentHandler(xh); 
     xr.parse(new InputSource(is.getByteStream())); 

     XMLStream xmlStream = XMLHandler.xmlStream; 

     for (int i=0; i<xmlStream.getClasses().size(); i++) 
     { 
      System.out.println("*** CLASS ***"); 
      System.out.println(xmlStream.getClasses().get(i).getClassName()); 
      System.out.println(xmlStream.getClasses().get(i).getType()); 
      for (int j=0; j<xmlStream.getClasses().get(i).getProperties().size(); j++) 
      { 
       System.out.println("*** PROP ***"); 
       System.out.println(xmlStream.getClasses().get(i).getProperties().get(j).getName()); 
       System.out.println(xmlStream.getClasses().get(i).getProperties().get(j).getType()); 
      } 
      for (int j=0; j<xmlStream.getClasses().get(i).getMethods().size(); j++) 
      { 
       System.out.println("*** METH ***"); 
       System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getName()); 
       System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getReturnType()); 
       for (int k=0; k<xmlStream.getClasses().get(i).getMethods().get(j).getParameters().size(); k++) 
       { 
        System.out.println("*** PARAMS ***"); 
        System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getParameters().get(k).getName()); 
        System.out.println(xmlStream.getClasses().get(i).getMethods().get(j).getParameters().get(k).getType()); 
       } 
      } 

     } 

    } catch (IOException ex) { 
     Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (ParserConfigurationException ex) { 
     Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (SAXException ex) { 
     Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

這條線時,該計劃遇到MalformedURLException異常: 「xr.parse(新的InputSource(是。 getByteStream()));」

有沒有人有什麼想法是什麼錯?

回答

2

保存XML文檔.xml文件(這份厚禮說),並嘗試這種方法來運行你的解析器:

XMLReader reader = XMLReaderFactory.createXMLReader(); 
XMLHandler xh = new XMLHandler(); 
reader.setContentHandler(xh); 
reader.parse(PATH_TO_FILE); 

,而不是你的代碼:

SAXParserFactory spf = SAXParserFactory.newInstance(); 
SAXParser sp = spf.newSAXParser(); 
XMLReader xr = sp.getXMLReader(); 
XMLHandler xh = new XMLHandler(); 

InputSource is = new InputSource(); 
is.setCharacterStream(new StringReader(xmlst)); 
xr.setContentHandler(xh); 
xr.parse(new InputSource(is.getByteStream())); 

希望它能幫助。

+0

有一個新的錯誤,但它與XMLHandler有關。我會盡力修復它並回復你。 – user1028408 2013-02-22 14:21:34

+0

@ user1028408,好的,我在線 – bsiamionau 2013-02-22 14:23:29

+0

好的,我已經修復了這個程序,它完美地工作。有一個小問題,我沒有在對象的構造函數中初始化列表。但是,我仍然希望使用直接輸入字符串來完成此操作,而不是從XML文件進行解析。你知不知道怎麼? – user1028408 2013-02-23 11:07:20