我有这个XML:
<menu>
<day name="monday">
<meal name="BREAKFAST">
<counter name="Bread">
<dish>
<name>Plain Bagel</name>
</dish>
<counter/>
<meal/>
<day/>
<day name="tuesday">
<meal name="LUNCH">
<counter name="Other">
<dish>
<name>Cheese Bagel</name>
</dish>
<counter/>
<meal/>
<day/>
<menu/>
如果day标签的属性等于星期一,那么现在就是我要做的。然后,饭标标记属性等于BREAKFAST
,然后我想得到计数器的属性。 &#34;面包&#34;
我已经设置了xml pull解析器,但我很难获得这个值。这是我尝试过的,现在我看到它无法工作......所以任何有关如何设置它的帮助都会很棒。
while (eventType != XmlResourceParser.END_DOCUMENT) {
String tagName = xmlData.getName();
switch (eventType) {
case XmlResourceParser.START_TAG:
if (tagName.equalsIgnoreCase("day")) {
if (xmlData.getAttributeValue(null, "name").equalsIgnoreCase(day)) {
if (tagName.equalsIgnoreCase("meal")) {
mealArray.add(xmlData.getAttributeValue(null, "name"));
Log.i(TAG, xmlData.getAttributeValue(null, "name"));
}
}
}
break;
case XmlResourceParser.TEXT:
break;
case XmlPullParser.END_TAG:
break;
}
eventType = xmlData.next();
}
答案 0 :(得分:6)
您需要添加用于解析嵌套标记的逻辑:
帮助您前进的一个非常简单的示例:
我解析了这个字符串:
<menu><day name=\"monday\"><meal name=\"BREAKFAST\"><meal/><day/></menu>
代码:
try {
factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader("<menu><day name=\"monday\"><meal name=\"BREAKFAST\"><meal/><day/></menu>"));
int eventType = xpp.getEventType();
while (eventType != XmlResourceParser.END_DOCUMENT) {
String tagName = xpp.getName();
switch (eventType) {
case XmlResourceParser.START_TAG:
if (tagName.equalsIgnoreCase("day")) {
if (xpp.getAttributeValue(null, "name").equalsIgnoreCase("MONDAY")) {
int eventType2 = xpp.next();
while (eventType2 != XmlResourceParser.END_DOCUMENT) {
String tagName2 = xpp.getName();
switch (eventType2) {
case XmlResourceParser.START_TAG:
if (tagName2.equalsIgnoreCase("meal")) {
Log.i("tag", "meal: " + xpp.getAttributeValue(null, "name"));
}
break;
case XmlResourceParser.TEXT:
break;
case XmlPullParser.END_TAG:
break;
}
eventType2 = xpp.next();
}
}
}
break;
case XmlResourceParser.TEXT:
break;
case XmlPullParser.END_TAG:
break;
}
eventType = xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
你看到了区别,对吧?
我添加了这个,基本上就是在获得我想要的那一天之后。 (就我而言,硬编码字符串"Monday"
。)
int eventType2 = xpp.next();
并以此eventType2
为基础,检索tagName2
将用于“用餐”
一个better example来帮助你以一种很好的方式编写你的逻辑。
希望这有帮助。
答案 1 :(得分:5)
首先,您的XML格式不正确。 在任何网站查看。说这个XML Validator
结束标记应该是这样的
&LT;饭> &LT; /饭&gt;
不=&gt; &LT;饭&gt;&lt;饭/&gt;
在下面将XML更正为响应字符串后, 你可以尝试这个代码,它的工作
String response = "<menu><day name=\"monday\"><meal name=\"BREAKFAST\"><counter name=\"Bread\"><dish><name>Plain Bagel</name></dish></counter></meal></day><day name=\"tuesday\"><meal name=\"LUNCH\"><counter name=\"Other\"><dish><name>Cheese Bagel</name></dish></counter></meal></day></menu>";
Document doc;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource isr = new InputSource();
isr.setCharacterStream(new StringReader(response));
doc = db.parse(isr);
try{
doc.getDocumentElement().normalize();
NodeList nodes = doc.getElementsByTagName("day");
for (int i = 0; i <= nodes.getLength(); i++) {
Node nNode = nodes.item(i);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("day"+eElement.getAttribute("name"));
System.out.println("meal"+eElement.getElementsByTagName("meal").item(0).getAttributes().getNamedItem("name").getNodeValue());
System.out.println("counter"+eElement.getElementsByTagName("counter").item(0).getAttributes().getNamedItem("name").getNodeValue());
System.out.println("dish :" + eElement.getElementsByTagName("name").item(0).getTextContent());
}
}
}
catch(Exception e){
}
希望这有帮助!
答案 2 :(得分:3)
好吧,现在就逻辑地看一下你的switch语句:
String tagName = xmlData.getName();
if (tagName.equalsIgnoreCase("day")) {
if( . . . ) {
if (tagName.equalsIgnoreCase("meal")) {
//do something
}
}
你看到那个问题吗?你永远不会tagName.equals("day")
和tagName.equals("meal")
都是真的!继续获取xmlData的子节点并获取它的名称,然后执行另一个if语句。
您需要在每个if之后更新tagName
的值。
答案 3 :(得分:3)
将您的信息存储在本地变量中,然后检查访问过的标签是否与您想要的模式相同,如果是,请执行您想要的操作。这是一个想法:
String currentDay;
String mealOfCurrentDay;
while (eventType != XmlResourceParser.END_DOCUMENT) {
String tagName = xmlData.getName();
switch (eventType) {
case XmlResourceParser.START_TAG:
if (tagName.equalsIgnoreCase("day"))
currentDay = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("meal"))
mealOfCurrentDay = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("counter ")){
// now we must check our stored pattern
// step one: day must be monday
if(currentDay != null && currentDay.equalsIgnoreCase("monday")){
// step tow: meal must be BREAKFAST
if(mealOfCurrentDay!= null && mealOfCurrentDay.equalsIgnoreCase("BREAKFAST")){
counter = xmlData.getAttributeValue(null, "name");
// Wow we have done :-)
}
else{
// no, it is not my desierd pattern so I clear my history
currentDay = "";
mealOfCurrentDay = "";
}
}else{
// no, it is not my desierd pattern so I clear my history
currentDay = "";
mealOfCurrentDay = "";
}
}
break;
case XmlResourceParser.TEXT:
break;
case XmlPullParser.END_TAG:
break;
}
eventType = xmlData.next();
}
答案 4 :(得分:2)
while (eventType != XmlResourceParser.END_DOCUMENT) {
String tagName = xmlData.getName();
switch (eventType) {
case XmlResourceParser.START_TAG:
if (tagName.equalsIgnoreCase("day")) {
day = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("meal")) {
meal = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("counter")) {
counter = xmlData.getAttributeValue(null, "name");
}
break;
case XmlResourceParser.TEXT:
data += xmlData.getText();
if (tagName.equalsIgnoreCase("name")) {
name= xmlData.getText();
}
break;
case XmlPullParser.END_TAG:
if (tagName.equals("day")) {
recordsFound++;
}
break;
}
publishProgress(new String[]{day,meal,counter});
eventType = xmlData.next();
}
首先,switch-case语句中缺少中断。 其次,始终从START_TAG案例中解析属性。标签内的文本在TEXT情况下解析,END_TAG对于根据其嵌套制作对象或arraylists非常有用。
onProgressUpdate必须如下所示:
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if (values.length == 0) {
Log.i(TAG, "no data");
}
else {
String day = values[0];
String meal= values[1];
String counter= values[2];
}
}
答案 5 :(得分:2)
首先,您的XML已损坏,请查看结束标记。应该是:
<menu>
<day name="monday">
<meal name="BREAKFAST">
<counter name="Bread">
<dish>
<name>Plain Bagel</name>
</dish>
</counter>
/</meal>
</day>
<day name="tuesday">
<meal name="LUNCH">
<counter name="Other">
<dish>
<name>Cheese Bagel</name>
</dish>
</counter>
</meal>
</day>
其次,考虑使用不是拉解析器,你使用了很多代码行,但是你的目标有更短的方法(例如XMLBeam(披露:我隶属于该项目强>)):
public class Test {
@XBDocURL("res://menu.xml")
public interface Menu {
@XBRead("//day[@name='monday']/meal[@name='BREAKFAST']/counter/@name")
String getCounterName();
}
@Test
public void testMenu() throws IOException {
String name = new XBProjector().io().fromURLAnnotation(Menu.class).getCounterName();
assertEquals("Bread", name);
}
}
答案 6 :(得分:2)
使用XPath并保持平静
package xml;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class XPathTest {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("sample.xml");
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath()
XPathExpression expr = xpath.compile("string(/menu/day[@name='monday']/meal[@name='BREAKFAST']/counter/@name))");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
return (String)result;
}
}