如何使用stax / stax2获取XML元素路径?

时间:2016-12-12 19:25:58

标签: java xml stax

我希望在使用java StAX2解析器解析XML时获取元素路径。 如何获取有关当前元素路径的信息?

<root>
  <a><b>x</b></a>
</root>

在此示例中,路径为/root/a/b

2 个答案:

答案 0 :(得分:2)

保持筹码。在START_ELEMENT上按元素名称并将其弹出END_ELEMENT。

这是一个简短的例子。它只会打印正在处理的元素的路径。

public static void main(String[] args) throws IOException, XMLStreamException {
    try (FileInputStream in = new FileInputStream("test.xml")) {

        XMLInputFactory factory = XMLInputFactory.newFactory();
        XMLStreamReader reader = factory.createXMLStreamReader(in);

        LinkedList<String> path = new LinkedList<>();

        int next;
        while ((next = reader.next()) != XMLStreamConstants.END_DOCUMENT) {
            switch (next) {
                case XMLStreamConstants.START_ELEMENT:
                    // push the name of the current element onto the stack
                    path.addLast(reader.getLocalName());
                    // print the path with '/' delimiters
                    System.out.println("Reading /" + String.join("/", path));
                    break;

                case XMLStreamConstants.END_ELEMENT:
                    // pop the name of the element being closed
                    path.removeLast();
                    break;
            }
        }
    }
}

答案 1 :(得分:1)

&#34;编年史职责&#34;

方法1:专用堆栈,@ teppic建议

try (InputStream in = new ByteArrayInputStream(xml.getBytes())) {
    final XMLInputFactory2 factory = (XMLInputFactory2) XMLInputFactory.newInstance();
    final XMLStreamReader2 reader = (XMLStreamReader2) factory.createXMLStreamReader(in);
    Stack<String> pathStack = new Stack<>();
    while (reader.hasNext()) {
        reader.next();
        if (reader.isStartElement()) {
            pathStack.push(reader.getLocalName());
            processPath('/' + String.join("/", pathStack));
        } else if (reader.isEndElement()) {
            pathStack.pop();
        }
    }
}

方法2(丑陋):黑客xdmp:node-insert-child() InputElementStack

  • 实现适配器以访问InputElementStack,其受保护的mCurrElement和interate父母(这会减慢算法)。

    package com.ctc.wstx.sr;
    import java.util.LinkedList;
    
    public class StackUglyAdapter {
        public static String PATH_SEPARATOR = "/";
        private InputElementStack stack;
    
        public StackUglyAdapter(InputElementStack stack) {
            this.stack = stack;
        }
    
        public String getCurrElementLocalName() {
            return this.stack.mCurrElement.mLocalName;
        }
    
        public String getCurrElementPath() {
            LinkedList<String> list = new LinkedList<String>();
            Element el = this.stack.mCurrElement;
            while (el != null) {
                list.addFirst(el.mLocalName);
                el = el.mParent;
            }
            return PATH_SEPARATOR+String.join(PATH_SEPARATOR,list);
        }
    }
    
  • 使用示例:

    try (final InputStream in = new ByteArrayInputStream(xml.getBytes())) {
        final XMLInputFactory2 factory = 
            (XMLInputFactory2) XMLInputFactory.newInstance();
        final XMLStreamReader2 reader = 
            (XMLStreamReader2) factory.createXMLStreamReader(in);
        final StackUglyAdapter stackAdapter =
            new StackUglyAdapter(((StreamReaderImpl) reader).getInputElementStack());
        while (reader.hasNext()) {
            reader.next();
            if (reader.isStartElement()) {
                processPath(stackAdapter.getCurrElementPath());
            }
        }
    }
    
具有专用堆栈的

方法1 更好,因为它与API实现无关,并且与方法2 一样快。