Получить значения атрибута тега на основе значения одного атрибута в xml - PullRequest
0 голосов
/ 20 сентября 2011

Я делаю приложение для 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>

Приложение будет иметь заданное имя (например, Джон, Эд, Мэри, Кейт), и я хотел бы получить значения атрибутов тега для той строки, в которой указано имя и в каком атрибуте находится имя ( например, name1, name2), имя останется прежним, но оно будет сдвигать строки и атрибуты в зависимости от недели.

Я искал ответ и обнаружил, что, скорее всего, буду использовать XPath. Может ли кто-нибудь помочь мне с тем, как я мог бы сделать это? Имеет ли значение мой метод синтаксического анализа для использования xpath? ДОМ или САКС?

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 20 сентября 2011

Документация к пакету для 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'].

Если вам необходимо сопоставить оба значения name1 и name2, используйте вместо этого этот тест узла: [@name1='%s' or @name2='%s']. В этом случае вам, вероятно, также потребуется получить NodeList из evaluate() для обработки нескольких совпадений:

NodeList c = (NodeList) xpath.evaluate(expr, xml, XPathConstants.NODESET);
0 голосов
/ 20 сентября 2011

Ответ на вопрос относительно xpath, вероятно, является наилучшим способом. Однако, если вы хотите создать POJO из графика xml, вы можете десериализовать xml, используя что-то вроде XStream, или в более сложных структурах xml, вы можете создать схему из xml, используя Trang, а затем создать классы java, используя jaxb. xjc tool.

Используя ваш пример, я написал небольшую программу, которая показывает, как вы можете сделать это с помощью 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());
    }
}

}

...