2012-06-25 12 views
9

tengo una entrada de cadena de la que necesito para extraer información sencilla, aquí está el código XML de muestra (de mkyong):XML no análisis de cadenas como entrada con el saxofón

<?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> 

Cómo analizarlo dentro de mi código (tengo un campo String name en mi clase):

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; 
    } 

estoy un java.io.FileNotFoundException y veo que está tratando de encontrar un archivo myprojectpath + the entireStringXML

Qué am Estoy haciendo mal?

Addon:

Aquí es mi método principal:

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

alguna razón en particular por la que no puede escribir la cadena XML en un archivo XML y extrae de esa manera? –

+0

@Kamron K. sí, porque estoy escribiendo una función definida por el usuario de la colmena (https://cwiki.apache.org/Hive/languagemanual-udf.html). Escaneo un montón de registros en una base de datos no relacional y cada registro tiene un pequeño fragmento de xml almacenado en un registro. –

Respuesta

42

Debe reemplazar la línea saxParser.parse(xml.toString(), handler); con la siguiente:

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

usted señor son impresionantes –

+1

gracias, ayudó mucho – deadfish

1

Mybe esta ayuda. se utiliza javax.xml.parsers.DocumentBuilder, que es más fácil que SAX

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; 
    } 

puede recorrer el documento utilizando NodeList y comprobar cada nodo por su nombre

0

Parece que tomó este ejemplo de here. Debe pasar un archivo con ruta absoluta y no una cadena al método SAXParser.parse(); Mire el ejemplo de cerca. El método parse()defined as sigue

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

Si desea analizar una cadena de todos modos. Hay otro método que toma Inputstream.

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

Luego hay que convertir su cadena a un InputStream. Aquí está how to do it.

0

te llaman de análisis con un String como primer parámetro. De acuerdo con el docu esa cadena se interpreta como URI en su archivo.

Si desea analizar su String directamente, hay que transformarlo a un InputStream en el primer lugar para el uso con el método parse(InputSource is, DefaultHandler dh) (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

voy a poner de relieve otro tema , que es probable que golpee una vez que lea su archivo correctamente.

El método

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

no siempre le dará el elemento de texto completo. Es libre de darle el elemento de texto (contenido) 'n' caracteres a la vez.De the doc:

analizadores SAX pueden devolver todos los datos de caracteres contiguos en un solo trozo, o pueden dividirlo en varios trozos

Por lo que debe construir su cadena de elementos de texto de cada llamada a este método (por ejemplo, usando un StringBuilder) y solo interpreta/almacena ese texto una vez que se llama al método endElement() correspondiente.

Esto puede no afectarle ahora. Pero surgirá en algún momento en el futuro, probablemente cuando menos lo esperes. Lo he encontrado al pasar de documentos XML pequeños a grandes, donde el almacenamiento en búfer ha podido contener todo el documento pequeño, pero no el más grande.

Un ejemplo (en pseudo-código):

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 para el sin embargo, ¿puede dar un ejemplo de cómo hacerlo en el 'endElement()' por favor. gracias. Siento que esto es importante de lo que estás hablando –

+0

@Gandalf - ahora listo. Ver arriba para pseudocódigo. –

+0

gracias por la respuesta, ¿es esto correcto? http://justpaste.it/12w3 ¿Te refieres a esto? (Agregué el acuerdo) –