【问题标题】:How to get XPath of all Nodes in XML by using Java or Scala?如何使用 Java 或 Scala 获取 XML 中所有节点的 XPath?
【发布时间】:2018-02-03 10:48:52
【问题描述】:

我想使用 Java 或 Scala 获取 XML 中所有节点的 XPath 吗?

<foo>
    <foo1>Foo Test 1</foo1>
    <foo2>
        <another1>
            <test10>This is a duplicate</test10>
        </another1>
    </foo2>
    <foo2>
        <another1>
            <test1>Foo Test 2</test1>
        </another1>
    </foo2>
    <foo3>Foo Test 3</foo3>
    <foo4>Foo Test 4</foo4>
</foo>

输出

foo
foo/foo2/
/foo/foo2/another1/

【问题讨论】:

    标签: java xml scala xpath


    【解决方案1】:

    我认为您需要使用StAX parser。考虑以下代码:

    public class XmlPathIterator implements Iterator<String> {
        private static XMLInputFactory factory = XMLInputFactory.newFactory();
        private final XMLStreamReader xmlReader;
        private List<String> tags = new ArrayList<>(); // really need just Stack but it is old and Vector-based
    
        public XmlPathIterator(XMLStreamReader xmlReader) {
            this.xmlReader = xmlReader;
            moveNext();
        }
    
        public static XmlPathIterator fromInputStream(InputStream is) {
            try {
                return new XmlPathIterator(factory.createXMLStreamReader(is));
            } catch (XMLStreamException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static XmlPathIterator fromReader(Reader reader) {
            try {
                return new XmlPathIterator(factory.createXMLStreamReader(reader));
            } catch (XMLStreamException e) {
                throw new RuntimeException(e);
            }
        }
    
        private void moveNext() {
            try {
                while (xmlReader.hasNext()) {
                    int type = xmlReader.next();
                    switch (type) {
                        case XMLStreamConstants.END_DOCUMENT:
                            tags.clear(); // finish
                            return;
    
                        case XMLStreamConstants.START_ELEMENT:
                            QName qName = xmlReader.getName();
                            tags.add(qName.getLocalPart());
                            return;
    
                        case XMLStreamConstants.END_ELEMENT:
                            tags.remove(tags.size() - 1);
                            break; // but continue the loop!
    
                        // also continue  the loop on everything else
                    }
                }
            } catch (XMLStreamException ex) {
                throw new RuntimeException(ex); // just pass throw
            }
        }
    
        @Override
        public boolean hasNext() {
            return !tags.isEmpty();
        }
    
        @Override
        public String next() {
            String cur = "/" + String.join("/", tags);
            moveNext();
            return cur;
        }
    }
    

    它是String 的迭代器,它返回每个节点的 XPath。如果您的文件很小且适合内存,您可以轻松地从中构建一个List

    未处理的事情:

    1. 命名空间(因为您的示例没有),但您可以在 case XMLStreamConstants.START_ELEMENT 中修改从 QName 生成 String 的方式

    2. 在同一路径下有多个匹配标签的情况下的位置说明符。如果您只想获取唯一的字符串,您可以从此迭代器创建一个Set 以过滤掉重复项。

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 1970-01-01
      • 2017-02-24
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2015-08-22
      相关资源
      最近更新 更多