现在的位置: 首页 > 综合 > 正文

XML解析学习——创建XML

2017年12月25日 ⁄ 综合 ⁄ 共 10646字 ⁄ 字号 评论关闭

一.基础知识
  在前面的学习过程中,我们基本上比较全面的学习了OPhone/Android平台上读取XML文档的方法,介绍了使用Java SAX、OPhone/Android SAX、DOM和Pull等各种方式来读取XML文档内容。
  目前为止,我们一直专注于解析已有的XML文档,实际上我们也是需要读XML的情形比较多。但是我们可能也有写XML的需要,应用程序可能需要将 XML 发送到远程服务器,或者需要以XML的形式保存数据等。因此在这部分内容中我们就来学习下OPhone/Android平台上创建XML的方法。
  OPhone/Android系统中和创建XML相关的包为org.xmlpull.v1,在这个包中不仅提供了用来解析XML的Pull方式解析器XmlPullParser,还提供了一个用于创建XML的XmlSerializer。XmlSerializer没有像XmlPullParser那样提取XML事件,而是把它们推出到数据流OutputStream或Writer中。XmlSerializer提供了很直观的API,即使用startDocument开始文档,endDocument结束文档,startTag开始元素,endTag结束元素,text添加文本等。

  下面我们就用上面介绍的创建XML方式来实现把解析出来的USGS地震数据重新保存为一个更简单的XML文件的Demo例子。

  二.实例开发
  我们要完成的效果图如下图1所示:

  图1 创建XML

  首先解析USGS的地震数据并以ListView的方式显示,然后点击最上方的"Create XML"按钮就会重新把解析获得的地震数据重新创建为一个XML文件。
  新建一个OPhone工程OPhoneXMLDemoSerialize。
  添加进之前Demo工程OPhoneXMLDemoSaxII中的EarthquakeEntry.java和OPhoneSaxEarthquakeHandler.java文件。如果需要从本地读取xml数据的话,同时在assets文件夹下添加保存为xml格式了的USGS地震数据USGS_Earthquake_1M2_5.xml,如果需要联网读取的话,在manifest.xml文件中添加权限:

  1. <uses-permission android:name="android.permission.INTERNET" />  

  并修改res/layout下的main.xml为:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:orientation="vertical"  
  4.   android:layout_width="fill_parent"  
  5.   android:layout_height="fill_parent"  
  6.   >  
  7.   <Button  
  8.    android:id="@+id/serializeBtn"  
  9.   android:layout_width="fill_parent"   
  10.   android:layout_height="wrap_content"  
  11.    >  
  12.   </Button>  
  13.   <ListView  
  14.   android:id="@+id/list"  
  15.   android:layout_width="fill_parent"   
  16.   android:layout_height="fill_parent"  
  17.   />  
  18.   </LinearLayout>  

  接下来就来新建添加一个类SerializeEarthquakeHandler,用来创建XML,内容如下:

  1. public class SerializeEarthquakeHandler {  
  2.   
  3.    //写Xml数据  
  4.    public String writeXml(ArrayList<EarthquakeEntry> earthquakeEntryList)  
  5.    {  
  6.     StringWriter xmlWriter = new StringWriter();  
  7.     try {  
  8.      //创建XmlSerializer,有两种方式  
  9.      XmlPullParserFactory pullFactory;  
  10.      //方式一:使用工厂类XmlPullParserFactory的方式  
  11.      pullFactory = XmlPullParserFactory.newInstance();  
  12.      XmlSerializer xmlSerializer = pullFactory.newSerializer();  
  13.      //方式二:使用Android提供的实用工具类android.util.Xml  
  14.   //   XmlSerializer xmlSerializer = Xml.newSerializer();   
  15.   
  16.     xmlSerializer.setOutput(xmlWriter);  
  17.      //开始具体的写xml  
  18.      //<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>  
  19.      xmlSerializer.startDocument("UTF-8"true);  
  20.      //<feed number="25">  
  21.      xmlSerializer.startTag("""feed");  
  22.      xmlSerializer.attribute("""number", String.valueOf(earthquakeEntryList.size()));  
  23.      for(EarthquakeEntry earthquakeEntry : earthquakeEntryList)  
  24.      {  
  25.       //<entry>  
  26.       xmlSerializer.startTag("""entry");  
  27.       //<title>Vanuatu</title>  
  28.       xmlSerializer.startTag("""title");  
  29.       xmlSerializer.text(earthquakeEntry.getPlace());  
  30.       xmlSerializer.endTag("""title");  
  31.       //<magnitude>5.3</magnitude>  
  32.       xmlSerializer.startTag("""magnitude");  
  33.       xmlSerializer.text(String.valueOf(earthquakeEntry.getMagnitude()));  
  34.       xmlSerializer.endTag("""magnitude");  
  35.       //<updated>2010-09-26 06:44:37</updated>  
  36.       xmlSerializer.startTag("""updated");  
  37.       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  38.       String dateString = sdf.format(earthquakeEntry.getDate());  
  39.       xmlSerializer.text(dateString);  
  40.       xmlSerializer.endTag("""updated");  
  41.       //<link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/us2010brar.php</link>  
  42.       xmlSerializer.startTag("""link");  
  43.       xmlSerializer.text(earthquakeEntry.getLink());  
  44.       xmlSerializer.endTag("""link");  
  45.       //<latitude>-14.3009</latitude>  
  46.       xmlSerializer.startTag("""latitude");  
  47.       xmlSerializer.text(String.valueOf(earthquakeEntry.getLocation().getLatitude()));  
  48.       xmlSerializer.endTag("""latitude");  
  49.       //<longitude>167.9491</longitude>  
  50.       xmlSerializer.startTag("""longitude");  
  51.       xmlSerializer.text(String.valueOf(earthquakeEntry.getLocation().getLongitude()));  
  52.       xmlSerializer.endTag("""longitude");  
  53.       //<elev>-80100.0</elev>  
  54.       xmlSerializer.startTag("""elev");  
  55.       xmlSerializer.text(String.valueOf(earthquakeEntry.getElev()));  
  56.       xmlSerializer.endTag("""elev");  
  57.       //</entry>  
  58.       xmlSerializer.endTag("""entry");  
  59.      }  
  60.      //</feed>  
  61.      xmlSerializer.endTag("""feed");  
  62.      xmlSerializer.endDocument();  
  63.     } catch (Exception e) {  
  64.      // TODO Auto-generated catch block  
  65.      e.printStackTrace();  
  66.     }  
  67.     return xmlWriter.toString();    
  68.    }  
  69.   }  

  在创建XML的方法中
   //写Xml数据
   public String writeXml(ArrayList<EarthquakeEntry> earthquakeEntryList)
  首先创建XmlSerializer,
     //创建XmlSerializer,有两种方式
     XmlPullParserFactory pullFactory;
     //方式一:使用工厂类XmlPullParserFactory的方式
     pullFactory = XmlPullParserFactory.newInstance();
     XmlSerializer xmlSerializer = pullFactory.newSerializer();
     //方式二:使用Android提供的实用工具类android.util.Xml
  //   XmlSerializer xmlSerializer = Xml.newSerializer();
  创建XmlSerializer有两种方式,一种是使用我们介绍的org.xmlpull.v1包中的工厂类XmlPullParserFactory。除了这种方式外,还可以使用OPhone/Android SDK提供的实用工具包android.util中的类Xml的newSerializer()方法直接创建。
  接着为XmlSerializer设置一个输出的Writer,
  xmlSerializer.setOutput(xmlWriter);
  这里将事件推送到了一个 java.io.StringWriter 实例中。
  然后就可以使用具体的startDocument开始文档,endDocument结束文档,startTag开始元素,endTag结束元素,text添加文本等方法来创建具体的XML文档内容,具体方法参考上面的代码部分。从代码中我们可以看到,使用XmlSerializer创建XML还是相当直观和方便的。
  最后添加OPhoneXMLDemoSerialize.java文件中的内容为:

  1. public class OPhoneXMLDemoSerialize extends Activity {  
  2.   /** Called when the activity is first created. */  
  3.    //定义显示的List相关变量  
  4.    ListView list;  
  5.    Button serializeBtn;  
  6.    ArrayAdapter<EarthquakeEntry> adapter;  
  7.    ArrayList<EarthquakeEntry> earthquakeEntryList;  
  8.   @Override  
  9.   public void onCreate(Bundle savedInstanceState) {  
  10.   super.onCreate(savedInstanceState);  
  11.   setContentView(R.layout.main);  
  12.   //用于创建XML的按钮  
  13.     serializeBtn = (Button)findViewById(R.id.serializeBtn);  
  14.     serializeBtn.setEnabled(false);  
  15.   //获取地震数据流  
  16.   InputStream earthquakeStream = readEarthquakeDataFromFile();  
  17.   //Android Sax方式进行解析  
  18.   AndroidSaxEarthquakeHandler androidSaxHandler = new AndroidSaxEarthquakeHandler();  
  19.   earthquakeEntryList = androidSaxHandler.parse(earthquakeStream);  
  20.     //用ListView进行显示  
  21.     list = (ListView)this.findViewById(R.id.list);  
  22.     adapter = new ArrayAdapter<EarthquakeEntry>(this, android.R.layout.simple_list_item_1, earthquakeEntryList);  
  23.     list.setAdapter(adapter);  
  24.     serializeBtn.setEnabled(true);  
  25.     //点击按钮开始创建XML  
  26.     serializeBtn.setOnClickListener(new OnClickListener() {   
  27.      @Override  
  28.      public void onClick(View v) {  
  29.       // TODO Auto-generated method stub  
  30.       //构造xml  
  31.       SerializeEarthquakeHandler serializeHandler = new SerializeEarthquakeHandler();  
  32.       String earthquakeXml = serializeHandler.writeXml(earthquakeEntryList);  
  33.       //Log打印写成的xml数据  
  34.       Log.v("XmlSerialize", earthquakeXml);          
  35.       //把写成的xml数据输出到文件  
  36.       OutputStream outStream;  
  37.       try {  
  38.        outStream = openFileOutput("earthquake.xml", MODE_PRIVATE);  
  39.        OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream);  
  40.        outStreamWriter.write(earthquakeXml);  
  41.        outStreamWriter.close();  
  42.        outStream.close();  
  43.       } catch (Exception e) {  
  44.        // TODO Auto-generated catch block  
  45.        e.printStackTrace();  
  46.       }  
  47.      }  
  48.     });  
  49.   }  
  50.   
  51.   private InputStream readEarthquakeDataFromFile()  
  52.   {  
  53.     //从本地获取地震数据  
  54.     InputStream inStream = null;  
  55.     try {  
  56.      inStream = this.getAssets().open("USGS_Earthquake_1M2_5.xml");  
  57.     } catch (IOException e) {  
  58.      // TODO Auto-generated catch block  
  59.      e.printStackTrace();  
  60.     }  
  61.     return inStream;  
  62.   }  
  63.   private InputStream readEarthquakeDataFromInternet()  
  64.   {  
  65.    //从网络上获取实时地震数据  
  66.    URL infoUrl = null;  
  67.    InputStream inStream = null;  
  68.    try {  
  69.      infoUrl = new URL("http://earthquake.usgs.gov/earthquakes/catalogs/1day-M2.5.xml");  
  70.      URLConnection connection = infoUrl.openConnection();  
  71.      HttpURLConnection httpConnection = (HttpURLConnection)connection;  
  72.      int responseCode = httpConnection.getResponseCode();  
  73.      if(responseCode == HttpURLConnection.HTTP_OK)  
  74.      {  
  75.       inStream = httpConnection.getInputStream();  
  76.      }  
  77.     } catch (MalformedURLException e) {  
  78.      // TODO Auto-generated catch block  
  79.      e.printStackTrace();  
  80.     } catch (IOException e) {  
  81.      // TODO Auto-generated catch block  
  82.      e.printStackTrace();  
  83.     }  
  84.     return inStream;  
  85.   }  
  86.   }  

  程序前部分是使用OPhone/Android SAX的方式解析XML文档,然后在按钮的点击回调函数中把解析获得的地震数据重新创建为XML文档的形式,并分别用Log打印和保存为文件。

  1. //点击按钮开始创建XML  
  2.    serializeBtn.setOnClickListener(new OnClickListener() {   
  3.     @Override  
  4.     public void onClick(View v) {  
  5.      // TODO Auto-generated method stub  
  6.      //构造xml  
  7.      SerializeEarthquakeHandler serializeHandler = new SerializeEarthquakeHandler();  
  8.      String earthquakeXml = serializeHandler.writeXml(earthquakeEntryList);  
  9.      //Log打印写成的xml数据  
  10.      Log.v("XmlSerialize", earthquakeXml);          
  11.      //把写成的xml数据输出到文件  
  12.      OutputStream outStream;  
  13.      try {  
  14.       outStream = openFileOutput("earthquake.xml", MODE_PRIVATE);  
  15.       OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream);  
  16.       outStreamWriter.write(earthquakeXml);  
  17.       outStreamWriter.close();  
  18.       outStream.close();  
  19.      } catch (Exception e) {  
  20.       // TODO Auto-generated catch block  
  21.       e.printStackTrace();  
  22.      }  
  23.     }  
  24.    });  

   完成了,可以保存运行看下效果。
  当点击屏幕上方的"Create XML"按钮时,程序就会创建一个形式更加简单的XML文档,同时在DDMS的LogCat里打印出创建的XML文档内容,如下图2所示:

  图2 Log打印出的创建的XML文档内容

  同时还会把创建的XML以文件的形式保存在系统中,我们可以在DDMS的File Explorer的data/data/com.ichliebephone.xml.serialize/files文件夹下看到,如下图3所示:

  图3 保存着的创建出来的XML文件

  并且我们可以把这个文件导出到电脑上,可以看到里面的内容为:

  1. <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>  
  2.   <feed number="25">  
  3.    <entry>  
  4.     <title>Vanuatu</title>  
  5.     <magnitude>5.3</magnitude>  
  6.     <updated>2010-09-26 06:44:37</updated>  
  7.     <link>http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/us2010brar.php</link>  
  8.     <latitude>-14.3009</latitude>  
  9.     <longitude>167.9491</longitude>  
  10.     <elev>-80100.0</elev>  
  11.    </entry>  
  12.    <entry>  
  13.     <!-- 还有entry条目,省略-->  
  14.    </entry>  
  15.   </feed>  

  就是我们解析获得的所有地震条目,并且其中的各个元素及其内容、属性等按我们在SerializeEarthquakeHandler中指定的组织方式保存。

  三.总结
  在这块内容中我们学习了OPhone/Android平台上创建XML的方法,从以上的Demo例子中我们可以发现OPhone/Android上不仅解析XML方式多,并且方便,而且创建XML也是很方便直观,好理解和实现的。
  到这块为止,我们就学习完了OPhone/Android平台上和XML相关的内容,包括解析和创建XML等和XML相关的读与写两个方面,有了这些基础,我想处理OPhone/Android上的XML文档等基本可以轻松应付了,希望以上的学习内容对你也有所帮助,感谢你一直的关注!

  注:
  参考资料:http://www.ibm.com/developerworks/cn/xml/x-android/

抱歉!评论已关闭.