1

假设我的 XML 树中有四个级别,其中级别 3 可以有相同的子两次,即在以下 XML 中:

<Game>
    <Round>
        <roundNumber>1</roundNumber>
        <Door>
            <doorName>abd11</doorName>
            <Value>
                <xVal1>0</xVal1>
                <xVal2>25</xVal2>
                <pVal>0.31</pVal>
            </Value>
            <Value>
                <xVal1>25</xVal1>
                <xVal2>50</xVal2>
                <pVal>0.04</pVal>
            </Value>
            <Value>
                <xVal1>50</xVal1>
                <xVal2>75</xVal2>
                <pVal>0.19</pVal>
            </Value>
            <Value>
                <xVal1>75</xVal1>
                <xVal2>100</xVal2>
                <pVal>0.46</pVal>
            </Value>
        </Door>
        <Door>
            <doorName>vvv1133</doorName>
            <Value>
                <xVal1>60</xVal1>
                <xVal2>62</xVal2>
                <pVal>1.0</pVal>
            </Value>
        </Door>
    </Round>
    <Round>
        <roundNumber>2</roundNumber>
        <Door>
            <doorName>eee</doorName>
            <Value>
                <xVal1>0</xVal1>
                <xVal2>-25</xVal2>
                <pVal>0.31</pVal>
            </Value>
            <Value>
                <xVal1>-25</xVal1>
                <xVal2>-50</xVal2>
                <pVal>0.04</pVal>
            </Value>
            <Value>
                <xVal1>-50</xVal1>
                <xVal2>-75</xVal2>
                <pVal>0.19</pVal>
            </Value>
            <Value>
                <xVal1>-75</xVal1>
                <xVal2>-100</xVal2>
                <pVal>0.46</pVal>
            </Value>
        </Door>
        <Door>
            <doorName>cc</doorName>
            <Value>
                <xVal1>-60</xVal1>
                <xVal2>-62</xVal2>
                <pVal>0.3</pVal>
            </Value>
            <Value>
                <xVal1>-70</xVal1>
                <xVal2>-78</xVal2>
                <pVal>0.7</pVal>
            </Value>
        </Door>
    </Round>
</Game>

Doors每个都有两个Round,那么问题是,使用Domor Sax(或 Jdom 如果有帮助)可以

我在我的树上迭代并获取每个级别的数据?

此刻我“下降”了一个级别并获得了回合,这里:

  DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    Document doc = docBuilder.parse (new File("input.xml"));

    // normalize text representation
    doc.getDocumentElement ().normalize ();
    System.out.println ("Root element of the doc is " +    // would produce Game
         doc.getDocumentElement().getNodeName());


    NodeList roundNodes = doc.getElementsByTagName("Round");   // roundNodes are the Rounds 
    int totalNodes = roundNodes.getLength();                   // 2 by the example 
    System.out.println("Total number of Rounds are : " + totalNodes);   


    for (int i = 0; i < roundNodes.getLength() ; i++)

    {
        Node node = roundNodes.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE)
        {
            Element element = (Element)node;
            NodeList firstDoorList = element.getElementsByTagName("Door");
            Element firstDoorElement = (Element)firstDoorList.item(0);

            NodeList textFNList = firstDoorElement.getChildNodes();
            System.out.println("First Door : " + ((Node)textFNList.item(0)).getNodeValue().trim());
        }
    }

但似乎有很多迭代代码。

有没有一种简单的方法来提取该 XML 的数据?假设我每轮有 2 个 Doors 和一些 Rounds 数。

谢谢

4

1 回答 1

2

像这样解析内容是我编写SJXP的原因之一——我知道,我知道“天哪,不是另一个自制的库!”,但不要绝望,它是一个基于STAX 解析器规范,因此您不会像使用 DOM 那样使用 XPath 轻松获得开销。我用手写提要解析器(RDF、RSS、ATOM)一年多来构建它,我意识到我的工作越复杂,就越相似,所以我将核心租户提炼成一个单一的,简单快速的库(开销小于 SAX 解析器——它也可以在 Android 上运行,无需添加依赖项)。

该库的要点是定义一系列规则,针对您想要的 XML 中的所有元素。鉴于您要解析的所有 XML 数据都是 CHARACTER 数据(不是标签内的属性数据),您可以定义一系列字符规则,如下所示:

IRule roundNumRule = new DefaultRule(Type.CHARACTER, "/Game/Round/roundNumber") {
    @Override
    public void handleParsedCharacters(XMLParser parser, String text, Object userObject) {
        System.out.println("Round Parsed: " + text);
    }
}

IRule doorNameRule = new DefaultRule(Type.CHARACTER, "/Game/Round/Door/doorName") {
    @Override
    public void handleParsedCharacters(XMLParser parser, String text, Object userObject) {
        System.out.println("Door Name: " + text);
    }
}

...等等——其他规则的路径如下所示:

  • /游戏/回合/门/价值/xVal1
  • /游戏/回合/门/价值/xVal2
  • /游戏/回合/门/价值/pVal

在您拥有所有规则之后,您将像这样创建一个XMLParser 实例,并为其提供您创建的所有规则:

XMLParser parser = new XMLParser(roundNumRule, doorNameRule, <more rules>);

然后,您可以使用它来解析您的 XML,方法是通过其中一种解析方法向它提供表示 XML 流的任何有效InputStream实例。

您可以安全地反复重用 XMLParser 实例(只是不能同时在单独的线程中)。

您将需要尽可能多地跟踪您的状态,因为您知道您正在为哪个 roundNumber 加载 Door 值以及您正在使用哪个 Door 填充哪些值,但这很容易做到——只需创建简单的 Java POJO 来表示您的结构并将它们存储在 ArrayList 中,例如:

List<Round> roundList = new ArrayList<Round)();

假设你的“圆形”POJO 看起来像这样:

public class Round {
    public int number;
    public List<Door> doorList;
}

你的 Door POJO 看起来像:

public class Door {
    public String name;
    public int xVal1;
    public int yVal2;
    public double pVal;
}

顶级roundList将代表解析值的根,您可以将其直接传递给解析操作;这是您在SJXP Javadocs 中看到的用户对象。

当规则匹配时会发生什么,它将该 userObject 传递给规则,因此您将可以访问您传入的列表。

在roundNumRule 的情况下——您将创建一个新的Round POJO,为其分配roundNumber 值并将其添加到列表中。

在doorNameRule 的情况下——您将从列表中拉出最后一个Round,向它添加一个新的Door POJO 并将其名称分配给它。

等等...

我希望这会有所帮助!

于 2012-05-05T15:38:44.170 回答