【问题标题】:How to put nested XML file elements to list of objects with VTD-XML parser?如何使用 VTD-XML 解析器将嵌套的 XML 文件元素放入对象列表中?
【发布时间】:2015-09-28 13:41:59
【问题描述】:

我有很大的、非常嵌套的 XML 文件。所有实体和属性都将成为我的对象变量。我正在创建此类对象的列表。我知道如何用 DOM、SAX 和 XMLPullParser 来做这件事,它工作得很好,但我对 VTD 解析器有问题。解析后的ListView为空。我将 XML 文件的一部分和我的代码放在下面。也许有人知道我做错了什么。

<MedlineCitationSet>
<MedlineCitation Owner="NLM" Status="MEDLINE">
    <PMID Version="1">10540283</PMID>
    <DateCreated>
        <Year>1999</Year>
        <Month>12</Month>
        <Day>17</Day>
    </DateCreated>
    <Article PubModel="Print">
        <Journal>
            <ISSN IssnType="Print">0950-382X</ISSN>
            <JournalIssue CitedMedium="Print">
                <Volume>34</Volume>
                <Issue>1</Issue>
            </JournalIssue>...

我的安卓代码:

try {
        articlesList = new ArrayList<>();

        VTDGen vtdGen = new VTDGen();
        vtdGen.setDoc(bytes);
        vtdGen.parse(false);

        AutoPilot ap = new AutoPilot();
        VTDNav vtdNav = vtdGen.getNav();

        int i = -1;

        ap.bind(vtdNav);
        ap.selectXPath("/MedlineCitationSet/MedlineCitation");

        while ((ap.evalXPath()) != -1) {

            articlesList.add(new Article());
            String year = null, day = null, month = null;
            i++;

            if (vtdNav.hasAttr("Owner"))
                articlesList.get(i).setOwner(vtdNav.toNormalizedString(vtdNav.getAttrVal("Owner")));
            if (vtdNav.hasAttr("Status"))
                articlesList.get(i).setStatus(vtdNav.toNormalizedString(vtdNav.getAttrVal("Status")));

            vtdNav.push();

            AutoPilot ap1 = new AutoPilot();
            ap1.selectXPath("/MedlineCitationSet/MedlineCitation/PMID");
            ap1.bind(vtdNav);

            while ((ap1.evalXPath()) != -1) {
                articlesList.get(i).setPMID(vtdNav.toNormalizedString(vtdNav.getText()));
                articlesList.get(i).setVersion(vtdNav.toNormalizedString(vtdNav.getAttrVal("Version")));
            }

            ap1.resetXPath();
            ap1.selectXPath("/MedlineCitationSet/MedlineCitation/DateCreated");
            ap1.bind(vtdNav);

            while ((ap1.evalXPath() != -1)) {

                vtdNav.push();

                AutoPilot ap1x = new AutoPilot();
                ap1x.selectXPath("/MedlineCitationSet/MedlineCitation/DateCreated/Year");
                ap1x.bind(vtdNav);

                while ((ap1x.evalXPath()) != -1) {
                    year = vtdNav.toNormalizedString(vtdNav.getText());
                }

                ap1x.resetXPath();
                ap1x.selectXPath("/MedlineCitationSet/MedlineCitation/DateCreated/Month");
                ap1x.bind(vtdNav);

                while ((ap1x.evalXPath()) != -1) {
                    month = vtdNav.toNormalizedString(vtdNav.getText());
                }

                ap1x.resetXPath();
                ap1x.selectXPath("/MedlineCitationSet/MedlineCitation/DateCreated/Day");
                ap1x.bind(vtdNav);

                while ((ap1x.evalXPath()) != -1) {
                    day = vtdNav.toNormalizedString(vtdNav.getText());
                }

                articlesList.get(i).setDateCreated(day + "-" + month + "-" + year);

                vtdNav.pop();
            }

            ap1.resetXPath();
            ap1.selectXPath("/MedlineCitationSet/MedlineCitation/Article");
            ap1.bind(vtdNav);

            while ((ap1.evalXPath()) != -1) {

                if (vtdNav.hasAttr("Print"))
                    articlesList.get(i).setPubModel(vtdNav.toNormalizedString(vtdNav.getAttrVal("Print")));

                vtdNav.push();

                AutoPilot ap2 = new AutoPilot();
                ap2.selectXPath("/MedlineCitationSet/MedlineCitation/Article/Journal");
                ap2.bind(vtdNav);

                {
                    vtdNav.push();

                    AutoPilot ap2x = new AutoPilot();
                    ap2x.selectXPath("/MedlineCitationSet/MedlineCitation/Article/Journal/ISSN");
                    ap2x.bind(vtdNav);

                    while ((ap2x.evalXPath()) != -1) {
                        articlesList.get(i).setISSN(vtdNav.toNormalizedString(vtdNav.getText()));
                        articlesList.get(i).setIssnType(vtdNav.toNormalizedString(vtdNav.getAttrVal("IssnType")));
                    }

                    ap2x.resetXPath();
                    ap2x.selectXPath("/MedlineCitationSet/MedlineCitation/Article/Journal/JournalIssue");
                    ap2x.bind(vtdNav);

                    while ((ap2x.evalXPath()) != -1) {

                        articlesList.get(i).setCitedMedium(vtdNav.toNormalizedString(vtdNav.getAttrVal("CitedMedium")));

                        vtdNav.push();

                        AutoPilot ap3 = new AutoPilot();
                        ap3.selectXPath("/MedlineCitationSet/MedlineCitation/Article/Journal/JournalIssue/Volume");
                        ap3.bind(vtdNav);

                        while ((ap3.evalXPath()) != -1) {
                            articlesList.get(i).setVolume(vtdNav.toNormalizedString(vtdNav.getText()));
                        }

                        ap3.resetXPath();
                        ap3.selectXPath("/MedlineCitationSet/MedlineCitation/Article/Journal/JournalIssue/Issue");
                        ap3.bind(vtdNav);

                        while ((ap3.evalXPath()) != -1) {
                            articlesList.get(i).setIssue(vtdNav.toNormalizedString(vtdNav.getText()));
                        }

                        ap3.resetXPath();
                        vtdNav.pop();
                    }...

感谢您的帮助!

【问题讨论】:

  • 您尝试做的事情似乎很复杂,涉及多个嵌套的 xpath 表达式。你能先从概念上描述你想做的事情吗?
  • 我正在比较 4 个解析器的性能:XMLPullParser、DOM、SAX 和 VTD-XML。互联网上几乎没有 VTD-XML 解析器的示例,我对此有很大的问题。
  • VTD-XML 2.11 版本包含很多处理简单用例的示例。 VTD-XML 网站本身有一些示例。网站上也有文章和参考资料。您正在执行的任务非常复杂,似乎是一个经验丰富的 vtd-xml 开发人员的工作......让我知道我可以如何帮助你......
  • 使用其他解析器似乎要困难得多。明天我会尝试使用下面的示例,我会告诉你的。感谢您的帮助!
  • 它的学习曲线和其他任何东西一样。但是 vtd-xml 的目标是让简单任务或复杂任务尽可能简单……尤其是与 SAX 和 PULL 进行比较时

标签: java android xpath arraylist vtd-xml


【解决方案1】:

下面是一段代码 sn-p 帮助你提取文档中的相关字段。您对 AutoPilot 的使用存在问题。

例如,我建议你将所有的selectXPath移出while循环,因为它们是一个相对较慢的操作。 另外如果xml有深度嵌套,你应该考虑打开VTDGen的选择LcDepth 并将其设置为5。这有助于提高导航/xpath 性能。下面只是可以做的一个示例。同样对于简单的 XPath,您可以使用 VTDNav 的原生游标 API,它更方便...

如果您有任何问题,请告诉我...

    VTDGen vtdGen = new VTDGen();
     vtdGen.selectLcDepth(5);
     vtdGen.parseFile("c:\\xml\\agata.xml",false);
     AutoPilot ap = new AutoPilot(),ap1=new AutoPilot(), 
ap2=new AutoPilot(),ap3=new AutoPilot();
     VTDNav vn = vtdGen.getNav();
     int i = -1;
     ap.bind(vn);ap1.bind(vn);ap2.bind(vn);ap3.bind(vn);
     ap.selectXPath("/MedlineCitationSet/MedlineCitation");
     ap1.selectXPath("PMID");
     ap2.selectXPath("DateCreated");
     ap3.selectXPath("Article");
     while ((ap.evalXPath()) != -1) {
            String year = null, day = null, month = null;
            i++;

           if (vn.hasAttr("Owner"))     System.out.println("Owner==>"+vn.toNormalizedString(vn.getAttrVal("Owner")));
                        //articlesList.get(i).setOwner(vtdNav.toNormalizedString(vtdNav.getAttrVal("Owner")));
                    if (vn.hasAttr("Status"))
                        System.out.println("Stats==>"+vn.toNormalizedString(vn.getAttrVal("Status")));
                        //articlesList.get(i).setStatus(vtdNav.toNormalizedString(vtdNav.getAttrVal("Status")));
                    vn.push();
                    while((ap1.evalXPath())!=-1){
                        System.out.println("Version==>"+vn.toNormalizedString(vn.getAttrVal("Version")));
                        System.out.println("PMID==>"+vn.toNormalizedString(vn.getText()));
                    }
                    ap1.resetXPath();
                    vn.pop();
                    vn.push();
                    while((ap2.evalXPath())!=-1){
                        vn.toElement(VTDNav.FIRST_CHILD,"Year");
                        System.out.println("Year==>"+vn.toNormalizedString(vn.getText()));
                        vn.toElement(VTDNav.PARENT);
                        vn.toElement(VTDNav.FIRST_CHILD,"Month");
                        System.out.println("Month==>"+vn.toNormalizedString(vn.getText()));
                        vn.toElement(VTDNav.PARENT);
                        vn.toElement(VTDNav.FIRST_CHILD,"Day");
                        System.out.println("Day==>"+vn.toNormalizedString(vn.getText()));
                        vn.toElement(VTDNav.PARENT);
                    }
                    ap2.resetXPath();
                    vn.pop();
                    VN.push();
                    while((ap3.evalXPath())!=-1){
                          System.out.println("PubModel==>"+vn.toNormalizedString(vn.getAttrVal("PubModel")));
                    VN.pop();   


      }

【讨论】:

  • 我使用了您的示例,现在几乎可以使用了!列表中只有一个元素。看起来 main while 循环只进行了一次迭代。
  • 另外,当我使用 .parseFile() 方法(而不是 .setDoc() + .parse())时,我得到了 IllegalArgumentException 行:VTDNav vtdNav = vtdGen.getNav();
  • 你能把你的代码贴在某个地方让我更容易评论吗?
  • 请随时通过电子邮件将您遇到问题的代码通过电子邮件发送给我 (jzhang@ximpleware.com)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
  • 1970-01-01
  • 2013-09-17
  • 2012-02-21
相关资源
最近更新 更多