根据xml中一个属性的值获取标记属性值

时间:2011-09-19 20:09:14

标签: java android xml sax xpath-2.0

我正在为android做一个应用程序,并且正在从在线的xml文件中提取和解析标记属性的值。假设xml文件看起来像这样。

<a>
<b>
<c id="00001" time="1:00" day="Friday" name1="John" name2="Mary"></c>
<c id="00002" time="2:00" day="Monday" name1="Ed" name2="Kate"></c>
<c id="00003" time="3:00" day="Sunday" name1="Mary" name2="Ed"></c>
<c id="00004" time="4:00" day="Friday" name1="Kate" name2="John"></c>
</b>
</a>

应用程序将有一个设置名称(例如John,Ed,Mary,Kate),我想拉出标记属性的值,以显示名称所在的行和名称所属的属性(例如,name1,name2),名称将保持不变,但它将根据周来改变行和属性。

我搜索了答案,发现我很可能会使用XPath。任何人都可以帮我解决这个问题吗?我的解析方法对使用xpath很重要吗? DOM还是SAX?

提前致谢!

2 个答案:

答案 0 :(得分:2)

package documentation for javax.xml.xpath给出了一个很好的介绍,但这里也是一些示例代码:

InputSource xml = new InputSource(new StringReader("<a>\n" + 
    "<b>\n" + 
    "<c id=\"00001\" time=\"1:00\" day=\"Friday\" name1=\"John\" name2=\"Mary\"></c>\n" + 
    "<c id=\"00002\" time=\"2:00\" day=\"Monday\" name1=\"Ed\" name2=\"Kate\"></c>\n" + 
    "<c id=\"00003\" time=\"3:00\" day=\"Sunday\" name1=\"Mary\" name2=\"Ed\"></c>\n" + 
    "<c id=\"00004\" time=\"4:00\" day=\"Friday\" name1=\"Kate\" name2=\"John\"></c>\n" + 
    "</b>\n" + 
    "</a>"));

所以没有SAX,但任何DOM InputSource都可以。之后是:

String name = "John";

XPath xpath = XPathFactory.newInstance().newXPath();

// the String.format is just here so you can see the XPath expression more
// clearly without all the ".."+x+".." string concat, feel free to replace
String expr = String.format("//a/b/c[@name1='%s']", name);
Node c = (Node) xpath.evaluate(expr, xml, XPathConstants.NODE);

NamedNodeMap attribs = c.getAttributes();
String id = attribs.getNamedItem("id").getNodeValue();
String time = attribs.getNamedItem("time").getNodeValue();
// etc.

如果元素名称c在整个文档中是唯一的,则可以将XPath表达式减少到//c[@name1='%s']

如果您需要与name1name2进行匹配,请使用此节点测试:[@name1='%s' or @name2='%s']。在这种情况下,您可能还需要从NodeList获取evaluate()来处理多个匹配项:

NodeList c = (NodeList) xpath.evaluate(expr, xml, XPathConstants.NODESET);

答案 1 :(得分:0)

关于xpath的答案可能是最好的方法。但是,如果你想从xml图中实际创建POJO,你可以使用类似XStream的东西反序列化xml,或者在更复杂的xml结构中,你可以使用Trang从xml创建一个模式,然后使用jaxb创建java类。 xjc工具。

使用您的示例,我编写了一个小程序,演示如何使用XStream执行此操作: 您可以在此处获取XStream的二进制或源代码分发:http://x-stream.github.io/download.html

网站上有一些简单的例子,他们说它适用于Android。

这是我的代码:

package misc;

import java.io.Reader;
import java.io.StringReader;
import java.util.List;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

public class ProcessMyXml {
@XStreamAlias("c")
public static class c{
    //<c id="00001" time="1:00" day="Friday" name1="John" name2="Mary"></c>
    @XStreamAsAttribute
    String time;
    @XStreamAsAttribute
    String day;
    @XStreamAsAttribute
    String name1;
    @XStreamAsAttribute
    String name2;
    @Override
    public String toString() {
        return time+","+day+","+name1+","+name2;
    }

}

public static class bClass{
    @XStreamImplicit
    List<c> cList;
}
@XStreamAlias("a")
public static class a{
    bClass b;
}

public static void main(String[] args) {
    XStream xs = new XStream();
    xs.processAnnotations(a.class);
    Reader reader = new StringReader("<a>\n" + 
            "<b>\n" + 
            "<c id=\"00001\" time=\"1:00\" day=\"Friday\" name1=\"John\" name2=\"Mary\"></c>\n" + 
            "<c id=\"00002\" time=\"2:00\" day=\"Monday\" name1=\"Ed\" name2=\"Kate\"></c>\n" + 
            "<c id=\"00003\" time=\"3:00\" day=\"Sunday\" name1=\"Mary\" name2=\"Ed\"></c>\n" + 
            "<c id=\"00004\" time=\"4:00\" day=\"Friday\" name1=\"Kate\" name2=\"John\"></c>\n" + 
            "</b>\n" + 
            "</a>");

    a aFromFile = (a)xs.fromXML(reader);
    List<c> cList = aFromFile.b.cList;
    for(c current_c:cList){
        System.out.println(current_c.toString());
    }
}

}