2012-06-25 29 views
9

Tôi có một đầu vào chuỗi từ mà tôi cần phải trích xuất thông tin đơn giản, đây là xml mẫu (từ mkyong):Xml không phân tích cú pháp String như đầu vào với sax

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

Làm thế nào tôi phân tích nó trong mã của tôi (tôi có một lĩnh vực String name trong lớp học của tôi):

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

tôi nhận được một java.io.FileNotFoundException và tôi thấy rằng nó đang cố gắng để tìm một tập tin myprojectpath + the entireStringXML

gì am Tôi làm sai?

Addon:

Đây là phương pháp chính của tôi:

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

bất kỳ lý do đặc biệt tại sao bạn không thể viết chuỗi xml vào một tập tin xml và phân tích như vậy? –

+0

@Kamron K. yes, bởi vì tôi đang viết hàm xác định người dùng hive (https://cwiki.apache.org/Hive/languagemanual-udf.html). Tôi quét loạt các bản ghi trong cơ sở dữ liệu không quan hệ và mỗi bản ghi có một chút xml nhỏ được lưu trữ trong một bản ghi. –

Trả lời

42

Bạn nên thay thế dòng saxParser.parse(xml.toString(), handler); với những điều sau một:

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

bạn Thưa bạn là tuyệt vời –

+1

cảm ơn, nó đã giúp rất nhiều – deadfish

1

mybe trợ giúp này. nó sử dụng javax.xml.parsers.DocumentBuilder, đó là dễ dàng hơn 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; 
    } 

bạn có thể lặp qua các tài liệu bằng cách sử dụng NodeList và kiểm tra từng Node bởi đó là tên

0

Có vẻ bạn mất ví dụ này từ here. Bạn cần truyền một tệp có đường dẫn tuyệt đối không phải là một chuỗi đến phương thức SAXParser.parse(); Hãy xem ví dụ chặt chẽ. Phương pháp parse()defined as sau

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

Nếu bạn muốn phân tích một chuỗi anyways. Có một phương pháp khác mất Inputstream.

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

Sau đó, bạn cần phải chuyển đổi chuỗi của bạn đến một InputStream. Đây là how to do it.

0

Bạn gọi phân tích với một String như tham số đầu tiên. Theo số docu chuỗi đó được hiểu là URI vào tệp của bạn.

Nếu bạn muốn phân tích String của bạn trực tiếp, bạn phải chuyển đổi nó vào một InputStream ở nơi đầu tiên để sử dụng với các phương pháp 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

Tôi sẽ làm nổi bật vấn đề khác , mà bạn có khả năng nhấn khi bạn đọc tệp của mình một cách chính xác.

Phương pháp này

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

sẽ không luôn luôn cung cấp cho bạn các yếu tố văn bản hoàn chỉnh. It's at liberty để cung cấp cho bạn các yếu tố văn bản (nội dung) 'n' nhân vật tại một thời điểm.Từ the doc:

parsers SAX có thể trả lại toàn bộ dữ liệu nhân vật tiếp giáp trong một đoạn duy nhất, hoặc họ có thể chia nó thành nhiều khối

Vì vậy, bạn cần xây dựng chuỗi yếu tố văn bản của bạn từ mỗi cuộc gọi đến phương pháp này (ví dụ: sử dụng StringBuilder) và chỉ giải thích/lưu trữ văn bản đó khi phương thức endElement() tương ứng được gọi.

Điều này có thể không ảnh hưởng đến bạn ngay bây giờ. Nhưng nó sẽ phát sinh tại một thời điểm nào đó trong tương lai - có thể là khi bạn ít mong đợi nó nhất. Tôi đã gặp nó khi di chuyển từ các tài liệu XML nhỏ đến lớn, nơi mà bộ đệm đã có thể giữ toàn bộ tài liệu nhỏ, nhưng không phải là tài liệu lớn hơn.

Một ví dụ (trong pseudo-code):

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 cho mặc dù, bạn có thể cho một ví dụ về làm thế nào để làm điều đó trong 'endElement()' xin vui lòng. cảm ơn bạn. Tôi cảm thấy điều này quan trọng những gì bạn đang nói về –

+0

@Gandalf - đã hoàn tất. Xem ở trên cho mã giả. –

+0

cảm ơn phản hồi, điều này có đúng không? http://justpaste.it/12w3 có phải bạn đã nói điều này (tôi đã thêm sự kết thúc) –

Các vấn đề liên quan