【问题标题】:Android SAXParser, parse into array and get child nodesAndroid SAXParser,解析成数组并获取子节点
【发布时间】:2012-01-11 09:07:38
【问题描述】:

我正在开发一个小应用程序,该应用程序使用 xml 文件来打印章节的 ArrayList,该章节又指向特定的 html 文件。

我使用本教程开始:http://www.anddev.org/novice-tutorials-f8/parsing-xml-from-the-net-using-the-saxparser-t353.html

我的 xml 文件看起来像这样:

<chapters>
    <chapter title="Förutsättningar">
        <page title="Sida 3" url="sida_3.html" />
        <page title="Sida 4" url="sida_4.html" />
    </chapter>
</chapters>

使用上面的教程,我设法将每个章节节点输出到一个 ArrayList 中,每个项目上都有一个 onListItemClick 函数。到目前为止一切顺利。

我遇到的问题是当我单击一个项目时,我无法弄清楚如何获取特定的子节点并加载 html 文件。我对 Android 还是很陌生。

有什么想法吗?我真的很感谢任何关于这个主题的帮助。

这是我的来源:

ParsingXML.java

public class ParsingXML extends ListActivity {
private final String MY_DEBUG_TAG = "XmlParser";
public String lang = null;

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setTitle("Lastsäkring");

    Bundle bundle = this.getIntent().getExtras();
    lang = bundle.getString("lang");

    Log.i("ParsingXML", "Chosen language: " + this.lang + ", Type: " + this.lang.getClass().getName());

    TextView tv = new TextView(this);

    try {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();

        XMLReader xr = sp.getXMLReader();

        ExampleHandler myExampleHandler = new ExampleHandler();
        xr.setContentHandler(myExampleHandler);

        /*
         * If XML-file is located online (needs internet permissions in the manifest):
         * URL url = new URL("http://dev.houdini.se/android/demo.xml");
         * xr.parse(new InputSource(url.openStream()));
         */

        if(this.lang.equals("en"))
            xr.parse(new InputSource(this.getResources().openRawResource(R.raw.en_content)));
        else
            xr.parse(new InputSource(this.getResources().openRawResource(R.raw.sv_content)));

        ParsedExampleDataSet parsedExampleDataSet = myExampleHandler.getParsedData();                       
        this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, parsedExampleDataSet.toArrayList()));

    } catch(Exception e) {
        tv.setText("Error: " + e.getMessage());
        Log.e(MY_DEBUG_TAG, "XmlParseError", e);
        this.setContentView(tv);
    }
}

protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    Context context = getApplicationContext();
    int duration = Toast.LENGTH_SHORT;

    CharSequence text = "Clicked position: " + position + ", id: " + id;
    Toast toast = Toast.makeText(context, text, duration);
    toast.show();


    /*switch( position )
    {
       case 0:                                  
                Bundle bundle = new Bundle();
                bundle.putString("WindowTitle", "TESTA");
                Intent intent = new Intent(this, TextPage.class);
                intent.putExtras(bundle);
                startActivity(intent);
                break;                  
       case 1:  
            Intent video = new Intent(this, Video.class);
            startActivity(video);
           break;

       case 2:  
            Intent swipe = new Intent(this, Swipe.class);
            startActivity(swipe);
          break;
    }*/
}

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
        case R.id.settings:
            Intent prefsActivity = new Intent(getBaseContext(), Preferences.class);
            startActivity(prefsActivity);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
}

ExampleHandler.java

public class ExampleHandler extends DefaultHandler {
private boolean in_chapters = false;
private boolean in_chapter = false;
private boolean in_page = false;

private ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();

public ParsedExampleDataSet getParsedData() {
    return this.myParsedExampleDataSet;
}

@Override
public void startDocument() throws SAXException {
    this.myParsedExampleDataSet = new ParsedExampleDataSet();
}

@Override
public void endDocument() throws SAXException {
    // Nothing to do
}

@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    if(localName.equals("chapters")) {
        this.in_chapters = true;
    } else if(localName.equals("chapter")) {
        this.in_chapter = true;
        String attrValue = atts.getValue("title");
        myParsedExampleDataSet.setExtractedString(attrValue);
    } else if(localName.equals("page")) {
        this.in_page = true;
    }
}

@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
    if(localName.equals("chapters")) {
        this.in_chapters = false;
    } else if(localName.equals("chapter")) {
        this.in_chapter = false;
    } else if(localName.equals("page")) {
        this.in_page = false;
    }
}

@Override
public void characters(char ch[], int start, int length) {
    if(this.in_page == true) {
        myParsedExampleDataSet.setExtractedString(new String(ch, start, length));
    }
}

}

ParsedExampleDataSet.java

public class ParsedExampleDataSet {
private String extractedString = "";
private ArrayList<String> myArr = new ArrayList<String>();
private int extractedInt = 0;

public ArrayList<String> getExtractedString() {
    //return extractedString; Function Type = String
    return myArr;
}

public void setExtractedString(String extractedString) {
    //this.extractedString += extractedString + "\n";
    myArr.add(extractedString);
}

public int getExtractedInt() {
    return extractedInt;
}

public void setExtractedInt(int extractedInt) {
    this.extractedInt = extractedInt;
}

public String toString() {
    return "NODER\n" + this.extractedString;
}

public ArrayList<String> toArrayList() {
    return this.myArr;
}
}

【问题讨论】:

  • 老兄,如果有人帮助了你,请投票!
  • 声望达到 15 或更高才能投票。解决了我遇到的问题后,我会立即标记我接受的答案。
  • 对不起,我忘记了这个限制;/你有什么问题?
  • 打印我的章节时遇到了一些问题。检查 LAS_VEGAS 帖子上的 cmets :) stackoverflow.com/questions/8354598/…

标签: java android xml saxparser


【解决方案1】:

首先创建合适的数据结构:

public class PageNode {
    public String title;
    public String url;
    /* Getters/setter/constructor etc. if you feel like*/
    public String toString() {
       return title;
    }
}

public class ChapterNode {
    public String title;
    public ArrayList<PageNode> pages = new ArrayList<PageNode>();
    /* Getters/setter/constructor etc. if you feel like*/
}

并相应地解析 xml。示例:

ArrayList<ChapterNode> chapters = new ArrayList<ChapterNode>();
ChapterNode chapterNode = null;

public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    if(localName.equals("chapters")) {
    } else if(localName.equals("chapter")) {
        chapterNode = new ChapterNode();
        chapterNode.title = atts.getValue("title");
    } else if(localName.equals("page")) {
        PageNode pageNode = new PageNode();
        pageNode.title = atts.getValue("title");
        pageNode.url = atts.getValue("url");
        chapterNode.pages.add(pageNode);
    }
}

@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
    if(localName.equals("chapters")) {
    } else if(localName.equals("chapter")) {
        chapters.add(chapterNode);
        chapterNode = null;
    } else if(localName.equals("page")) {
    }
}

然后就可以这样访问pageNode了:

PageNode pageNode = chapterNode.pages.get(position);

并像这样设置适配器:

this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, chapterNode.pages));

【讨论】:

  • 这似乎是一个很好的解决方案。但是我将如何输出章节数组?以前,我是这样做的:ParsedExampleDataSet parsedExampleDataSet = myExampleHandler.getParsedData(); this.setListAdapter(new ArrayAdapter&lt;String&gt;(this, android.R.layout.simple_list_item_1, parsedExampleDataSet.toArrayList())); 我尝试编写一个函数,该函数刚刚从我的处理程序返回章节数组。它在我的 ArrayList 中打印了正确数量的项目,但标题有点奇怪。例如……“com.houdini.lathunden.ChapterNode@40535908”
  • 我编辑了我的答案,看看PageNode类的变化和我的答案。
  • 首先,感谢您的回答!我正试图解决这个问题。我已经按照您的建议进行了更改。但是,我不知道如何将 Chapters 数组从 ExampleHandler.java 获取到 ParsingXML.java(我将在其中打印它)。
  • 通过使用您的解决方案,我终于完成了所有工作。感谢您的帮助!
【解决方案2】:

当章节标签为真时,您必须检查布尔变量,您必须在一个数组列表中添加页面,当章节标签为假时,您必须将该数组列表添加到另一个全局数组列表中

【讨论】:

    【解决方案3】:

    (没有看过示例教程...)

    查看示例处理程序中startElement 的Attributes 参数。它应该包含 "url" 的值(看起来您只获得了 "title" 的值)。

    【讨论】:

      【解决方案4】:

      我习惯使用 DocumentBuilderFactory,所以我的解决方案是:

      首先,您应该像这样创建 ArrayHelper 类:

      public class ArrayHelper {
          public static ArrayList<HashMap<String, ?>> list = new ArrayList<HashMap<String, ?>>();
      }
      

      比:

      public class CoversParseTask extends AsyncTask<Void, Void, Boolean> {
      
          @Override
          protected void onPreExecute() {
      
          }
      
          @Override
          protected Boolean doInBackground(Void ... arg0) {
                  try {
                      DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
                      DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
                      document = dBuilder.parse(new InputSource(this.getResources().openRawResource(R.raw.en_content)));
                      document.getDocumentElement().normalize();  
                      NodeList nodeListIssue = document.getElementsByTagName("page");
      
                      for (int i = 0; i < nodeListIssue.getLength(); i++) {
                          HashMap<String, Object> temp = new HashMap<String, Object>();
                          Node node = nodeListIssue.item(i);
                          Element elementMain = (Element) node;
                          String pageID = elementMain.getAttribute("title");
                          String issueID = elementMain.getAttribute("url");
                          temp.put("title", pageID);
                          temp.put("url", issueID);
                          ArrayHelper.list.add(temp);
                      }
                  } catch (MalformedURLException e) {
                      e.printStackTrace();
                  } catch (ParserConfigurationException e) {
                      e.printStackTrace();
                  } catch (SAXException e) {
                      e.printStackTrace();
                  } catch (IOException e) {
                      e.printStackTrace();
                  };
              return false; 
          }
      
          @Override
          protected void onPostExecute(Boolean result) {
          //what happend if done.
          }
      }
      

      并像这样执行这个类:

      new CoversParseTask().execute();
      

      现在我们必须创建简单的适配器:

      SimpleAdapter adapter = new MySimpleAdapter(this, selectLastSearch(), R.layout.custom_row_view, new String[] { "Title", "Url" }, new int[] { R.id.title, R.id.url});
      

      我们的 MySimpleAdapter 看起来像这样:

      public class MySimpleAdapter extends SimpleAdapter {
          Context localcontext = null;
          public MySimpleAdapter(Context context,List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
              super(context, data, resource, from, to);
              localcontext = context;
          }
      
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
              View view = super.getView(position, convertView, parent);
              return view;
          }
      }
      

      没有将适配器设置为列表视图:

      listview.setAdapter(adapter);
      

      如果你想从列表中获取 URL,你应该像这样将列表添加到列表视图:

      listview.setOnItemClickListener(new OnItemClickListener() {
                  @Override
                  public void onItemClick(AdapterView<?> adapter, View view,
                          int position, long arg) {
                      Log.v("URL", ArrayHelper.list.get(position).get("url").toString());
                  }
              });
      

      仅此而已,希望能帮到你:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 2013-03-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多