2012-06-25 3 views
9

ich einen String-Eingang haben, von dem ich brauche einfach Informationen zu extrahieren, ist hier die XML-Probe (von mkyong):Xml nicht String als Eingabe mit Saxophon Parsen

<?xml version="1.0"?> 
<company> 
    <staff> 
     <firstname>yong</firstname> 
     <lastname>mook kim</lastname> 
     <nickname>mkyong</nickname> 
     <salary>100000</salary> 
    </staff> 
    <staff> 
     <firstname>low</firstname> 
     <lastname>yin fong</lastname> 
     <nickname>fong fong</nickname> 
     <salary>200000</salary> 
    </staff> 
</company> 

wie ich es in meinem Code zu analysieren (ich habe ein Feld String name in meiner Klasse):

public String getNameFromXml(String xml) { 
     try { 

      SAXParserFactory factory = SAXParserFactory.newInstance(); 
      SAXParser saxParser = factory.newSAXParser(); 
      DefaultHandler handler = new DefaultHandler() { 

       boolean firstName = false; 

       public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 

        if (qName.equalsIgnoreCase("firstname")) { 
         firstName = true; 
        } 
       } 

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

        if (firstName) { 
         name = new String(ch, start, length); 
         System.out.println("First name is : " + name); 
         firstName = false; 
        } 

       } 

      }; 

      saxParser.parse(xml.toString(), handler); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return name; 
    } 

ich erhalte ein java.io.FileNotFoundException und ich sehe, dass es sich um eine Datei myprojectpath + the entireStringXML

Was ist zu finden versucht, Ich mache falsch?

Addon:

Hier ist meine Hauptmethode:

public static void main(String[] args) { 
     Text tst = new Text("<?xml version=\"1.0\"?><company> <staff>  <firstname>yong</firstname>  <lastname>mook kim</lastname>  <nickname>mkyong</nickname>  <salary>100000</salary> </staff> <staff>  <firstname>low</firstname>  <lastname>yin fong</lastname>  <nickname>fong fong</nickname>  <salary>200000</salary> </staff></company>"); 
     NameFilter cc = new NameFilter(); 
     String result = cc.getNameFromXml(tst); 
     System.out.println(result); 
    } 
+0

ein Grund, insbesondere warum man kann die XML-Zeichenfolge in eine XML-Datei schreiben und auf diese Weise analysiert? –

+0

@Kamron K. Ja, weil ich hive benutzerdefinierte Funktion (https://cwiki.apache.org/Hive/languagemanual-udf.html) schreibe. Ich scanne einen Stapel von Datensätzen in einer nicht-relationalen Datenbank und jeder Datensatz enthält ein kleines Xml-Segment, das in einem Datensatz gespeichert ist. –

Antwort

42

Sie sollten die Zeile saxParser.parse(xml.toString(), handler); mit den folgenden ersetzen:

saxParser.parse(new InputSource(new StringReader(xml)), handler); 
+2

Sie Sir sind super –

+1

danke, es hat sehr geholfen – deadfish

1

Mybe diese Hilfe. es nutzt javax.xml.parsers.DocumentBuilder, die SAX einfacher als

ist
public Document getDomElement(String xml){ 
     Document doc = null; 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     try { 

      DocumentBuilder db = dbf.newDocumentBuilder(); 

      InputSource is = new InputSource(); 
       is.setCharacterStream(new StringReader(xml)); 
       doc = db.parse(is); 

      } catch (ParserConfigurationException e) { 
       Log.e("Error: ", e.getMessage()); 
       return null; 
      } catch (SAXException e) { 
       Log.e("Error: ", e.getMessage()); 
       return null; 
      } catch (IOException e) { 
       Log.e("Error: ", e.getMessage()); 
       return null; 
      } 
       // return DOM 
      return doc; 
    } 

Sie können Schleife durch das Dokument durch NodeList mit und jeder Knoten überprüfen, indem Sie seinen Namen

0

scheint, dass Sie von here dieses Beispiel nahm. Sie müssen eine Datei mit absolutem Pfad und keine Zeichenfolge an Methode SAXParser.parse() übergeben; Schauen Sie sich das Beispiel genau an. Das Verfahren parse()defined as folgt

public void parse(File f, 
        DefaultHandler dh) 
      throws SAXException, 
        IOException 

Wenn Sie einen String sowieso zu analysieren möchten. Es gibt eine andere Methode, die Inputstream nimmt.

public void parse(InputStream is, 
        DefaultHandler dh) 
      throws SAXException, 
        IOException 

Dann müssen Sie Ihre String in einen Inputstream konvertieren. Hier ist how to do it.

0

Sie rufen Parse mit einem String als ersten Parameter. Entsprechend der docu wird diese Zeichenkette als die URI zu Ihrer Datei interpretiert.

Wenn Sie Ihre String direkt analysieren wollen, müssen Sie es zu einem InputStream in erster Linie für die Verwendung zur Transformation mit der parse(InputSource is, DefaultHandler dh) Methode (docu):

// transform from string to inputstream 
ByteArrayInputStream in = new ByteArrayInputStream(xml.toString().getBytes()); 
InputSource is = new InputSource(); 
is.setByteStream(in); 

// start parsing 
saxParser.parse(xml.toString(), handler); 
2

Ich werde ein anderes Thema markieren , die Sie wahrscheinlich treffen werden, sobald Sie Ihre Datei richtig gelesen haben.

Verfahren

public void characters(char ch[], int start, int length) 

werden Sie nicht immer das komplette Textelement. Es steht Ihnen frei, Ihnen die Textelemente (Inhalt) und Zeichen gleichzeitig zu geben.Von the doc:

SAX-Parser können alle zusammenhängenden Zeichendaten in einem einzigen chunk zurückzukehren, oder sie können es in mehrere Stücke aufgeteilt

So sollten Sie mit Ihrem Textelement Zeichenfolge von jedem Anruf aufbauen Diese Methode (z. B. unter Verwendung einer StringBuilder) und nur diesen Text interpretieren/speichern, sobald die entsprechende endElement()-Methode aufgerufen wird.

Dies wirkt sich jetzt möglicherweise nicht auf Sie aus. Aber es wird irgendwann in der Zukunft entstehen - wahrscheinlich, wenn Sie es am wenigsten erwarten. Ich bin darauf gestoßen, als ich von kleinen zu großen XML-Dokumenten wechselte, wo die Pufferung das ganze kleine Dokument halten konnte, aber nicht das größere.

Ein Beispiel (in Pseudocode):

public void startElement() { 
     builder.clear(); 
    } 
    public void characters(char ch[], int start, int length) { 
     builder.append(new String(ch, start, length)); 
    } 
    public void endElement() { 
     // no do something with the collated text 
     builder.toString(); 
    } 
+0

+1 für das obwohl, können Sie ein Beispiel geben, wie es in der 'endElement()' bitte zu tun. Danke. Ich denke, das ist wichtig, worüber du redest –

+0

@Gandalf - jetzt fertig. Siehe oben für Pseudocode. –

+0

danke für die Antwort, ist das korrekt? http://justpaste.it/12w3 meinst du das? (Ich habe das Element hinzugefügt) –