选择跟随给定节点的节点

时间:2015-04-21 16:36:04

标签: java xml dom xpath

我必须使用DOM操作和XPath从iTunes Library XML文件中提取数据,格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Tracks</key>
    <dict>
        <dict>
            <key>Track ID</key><integer>203</integer>
            <key>Name</key><string>Winter</string>
            <key>Artist</key><string>Daughter</string>
            <!-- etc -->
            <key>Play Count</key><integer>2</integer>
            <key>Skip Count</key><integer>1</integer>
            <key>Track Type</key><string>File</string>
        </dict>
        <dict>
            Another set of track data, etc...
        </dict>
    </dict>
</dict>
</plist>

我需要能够从该文件中提取并存储数据位并将它们存储在数组中。 例如,我想将所有曲目名称存储在一个数组中,所有艺术家名称都存储在另一个数组中,但我不想存储其他值,例如播放/跳过计数。

我知道XPath的工作方式与此类似(如下面的switch语句所示),以便找到正确的位置,但键并不总是处于相同的位置。我正在有效地寻找一种基于前面值的值执行lookbehind断言的方法。

XPathExpression expr = xPath.compile("/plist/dict/dict/dict");
NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
StringBuilder outputString = new StringBuilder();

for (int i = 1; i <= nl.getLength(); i++) {
    for (int j = 0; j < 6; j++) {
        String label = "";
        switch (j) {
            case 0: expr = xPath.compile("/plist/dict/dict/dict["+i+"]/key[2]/text()");
                    //Append this value to TRACKNAME array with expr.evaluate
                    break;
            case 1: expr = xPath.compile("/plist/dict/dict/dict["+i+"]/key[3]/text()");
                    //Append this value to ARTIST array with expr.evaluate
                    break;
            case 2: /* ... */
        }
    }
}

1 个答案:

答案 0 :(得分:1)

如果你的xml代码是正确的,你可以尝试这个解决方案:

/plist//dict["+i+"]/key[contains(text(),'Track ID')]/following-sibling::*[1]

它为关键元素创造了条件 - 如果包含文本(f.e。&#39; Track ID&#39;),找到第一个兄弟元素 - 在本例中为整数,其值为203.

在后续兄弟之后使用star可以捕获每个第一个没有兴趣的元素,如果它是整数或字符串元素。