9

私はこの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 タグの属性が monday に等しい場合、ここで私がやろうとしていることは次のとおりです。そして、食事タグの属性が に等しい場合BREAKFAST、カウンターの属性を取得したいと思います。"パン"。

xml プル パーサーをセットアップしましたが、この値を取得するのに苦労しています。これが私が試したことです。今ではうまくいかないことがわかりました...だから、これを行うためにどのように設定できるかについての助けは素晴らしいでしょう.

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();
    }
4

7 に答える 7

7

ネストされたタグを解析するためのロジックを追加する必要があります。

先に進むのに役立つ非常に簡単な例:

この文字列を解析しました:

<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();
}

違いがわかりますよね?

基本的に、私が望んでいた日を取得した直後にこれを追加しました。(私の場合、ハードコードされた String "Monday"。)

int eventType2 = xpp.next();

そして、それに基づいて、 「食事」になるものをeventType2取得しましたtagName2

良い方法でロジックを書くのに役立つより良い例です。

お役に立てれば。

于 2014-12-19T14:01:36.887 に答える
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 ステートメントを実行します。

tagNameif ごとに値を更新する必要があります。

于 2014-12-15T02:57:13.180 に答える
3

まず、XML の形式が正しくありません。任意の Web サイトで確認してください。このXML Validatorで言う

終了タグは次のようにする必要があります

< 食事 > < /食事 >

ない => < 食事 >< 食事 />

以下の応答文字列として 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){
        
    }

お役に立てれば !

于 2014-12-18T10:59:29.443 に答える
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();
    }
于 2014-12-15T04:08:39.463 に答える
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;
}
}
于 2014-12-21T20:09:17.520 に答える
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);
}

}

于 2014-12-15T13:04:19.407 に答える