简体   繁体   English

使用xpath读取多个XML属性

[英]Reading multiple XML attributes with xpath

So say I have something like this: 所以说我有这样的事情:

<info>
    <collectorKey id="key"/>
    <credentials user="user" password="password"/>
    <Infos>
        <dummyInfo>
            <infoSource temp="N/A">               
                <tags>
                    <tag id="1" value="example"/>
                    <tag id="2" value="example"/>
                    <tag id="3" value="example"/>
                    <tag id="4" value="example"/>
                    <tag id="5" value="example"/>
                    <tag id="6" value="example"/>
                    <tag id="7" value="example"/>
                </tags>
            </infoSource>
        </dummyInfo>
    </Infos>
    <Infos>
        <dummyInfo>
            <infoSource temp="N/A">               
                <tags>
                    <tag id="1" value="example"/>
                    <tag id="2" value="example"/>
                    <tag id="3" value="example"/>
                    <tag id="4" value="example"/>
                    <tag id="5" value="example"/>
                    <tag id="6" value="example"/>
                    <tag id="7" value="example"/>
                </tags>
            </infoSource>
        </dummyInfo>
    </Infos>
</info>

and I want grab every tag attribute with the ID 2 and get the value for that tag. 我想获取ID为2的每个标签属性,并获取该标签的值。 Right now I have some long winded code to do it and it does not seem very practical. 现在,我有一些冗长的代码可以执行此操作,而且它似乎不太实用。 I'd like to convert it to use xpath if possible I was wondering how this would be done. 我想尽可能将其转换为使用xpath,我想知道如何实现。 I threw some skeleton code together but it's not garbing my tag values with 2. I presume some loop would need to be added along with some changes. 我把一些框架代码放在一起,但它并没有将我的标签值与2捆绑在一起。我认为需要添加一些循环以及一些更改。

Something like: 就像是:

try {
        ClassLoader classLoader = getClass().getClassLoader();
        File configProdXML = new File(classLoader.getResource("files/config-prod.xml").getFile());

        //parse it using a docbuilder
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = null;
        dBuilder = dbFactory.newDocumentBuilder();
        Document parsedConfig = dBuilder.parse(configProdXML);

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        XPathExpression expr = xpath.compile("/tags/tags/@id=2/text()");

        System.out.println(expr.toString());

side note. 边注。 Would xpath be the most practical thing with for this? 为此,xpath会是最实用的东西吗?

Yes, XPath is ideal for this: 是的,XPath非常适合:

XPathExpression expr = xpath.compile("//tags/tag[@id=2]/@example");

Some explanation: 一些解释:

  • The two slashes in //tags means all <tags> elements, at any level, anywhere in the document. //tags的两个斜杠表示文档中任何位置,任何级别的所有<tags>元素。
  • tag[@id=2] means <tag> elements, but with a predicate that restricts which elements qualify. tag[@id=2]表示<tag>元素,但带有限制哪些元素符合条件的谓词。

Normally, it isn't necessary to call XPath.compile directly, unless you plan to apply the same XPath to many different sources. 通常,除非计划将相同的XPath应用于许多不同的源,否则不必直接调用XPath.compile。 You can just call an evaluate method directly: 您可以直接调用evaluate方法:

NodeList values = (NodeList)
    xpath.evaluate("//tags/tag[@id=2]/@example", parsedConfig,
        XPathConstants.NODESET);

CAUTION: Never call URL.getFile(). 注意:切勿调用URL.getFile()。 It does not convert a URL into a valid file name—it just returns the portion of the URL after the host and port, which may contain percent-escapes for the many characters which are not allowed to appear in URLs. 它不会将URL转换为有效的文件名-只是返回URL在主机和端口之后的部分,其中可能包含许多不允许在URL中出现的字符的转义符。 Also, the URL returned by Class.getResource or ClassLoader.getResource is not guaranteed to point to a file at all; 同样,也不保证Class.getResource或ClassLoader.getResource返回的URL完全指向文件。 in particular, if you ever try to run from a .jar file, you will not get a file: URL. 特别是,如果您尝试从.jar文件运行,则不会获得file: URL。

Fortunately, you don't need a file. 幸运的是,您不需要文件。 You don't even need to parse a Document. 您甚至不需要解析文档。 You can just pass an InputStream directly to your XPath: 您可以将InputStream直接传递到XPath:

try (InputStream config = getClass().getResourceAsStream("/files/config-prod.xml")) {

    NodeList values = (NodeList)
        xpath.evaluate("//tags/tag[@id=2]/@example", new InputSource(config),
            XPathConstants.NODESET);

    int count = values.getLength();
    for (int i = 0; i < count; i++) {
        String value = values.item(i).getNodeValue();
        System.out.println("Found value \"" + value + "\"");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM