如何仅获取具有值 Stax 的元素

发布于 2024-09-10 20:17:06 字数 1793 浏览 2 评论 0原文

我试图只获取具有文本的元素,例如 xml :

<root>
      <Item>
        <ItemID>4504216603</ItemID>
        <ListingDetails>
          <StartTime>10:00:10.000Z</StartTime>
          <EndTime>10:00:30.000Z</EndTime>
          <ViewItemURL>http://url</ViewItemURL>
            ....
           </item> 

它应该打印

Element Local Name:ItemID
Text:4504216603
Element Local Name:StartTime
Text:10:00:10.000Z
Element Local Name:EndTime
Text:10:00:30.000Z
Element Local Name:ViewItemURL
Text:http://url

此代码还打印根、项目等。是否有可能,它一定是我只是无法谷歌它。

XMLInputFactory inputFactory = XMLInputFactory.newInstance();
InputStream input = new FileInputStream(new File("src/main/resources/file.xml"));
XMLStreamReader xmlStreamReader = inputFactory.createXMLStreamReader(input);

while (xmlStreamReader.hasNext()) {
    int event = xmlStreamReader.next();

    if (event == XMLStreamConstants.START_ELEMENT) {
    System.out.println("Element Local Name:" + xmlStreamReader.getLocalName());
    }

    if (event == XMLStreamConstants.CHARACTERS) {
                        if(!xmlStreamReader.getText().trim().equals("")){
                        System.out.println("Text:"+xmlStreamReader.getText().trim());
                        }
                }

            }

编辑不正确的行为

    Element Local Name:root
    Element Local Name:item
    Element Local Name:ItemID
    Text:4504216603
    Element Local Name:ListingDetails
    Element Local Name:StartTime
    Text:10:00:10.000Z
    Element Local Name:EndTime
    Text:10:00:30.000Z
    Element Local Name:ViewItemURL
    Text:http://url

我不希望打印没有文本的根节点和其他节点,只打印我上面写的输出。谢谢

I'm trying to get only elements that have text, ex xml :

<root>
      <Item>
        <ItemID>4504216603</ItemID>
        <ListingDetails>
          <StartTime>10:00:10.000Z</StartTime>
          <EndTime>10:00:30.000Z</EndTime>
          <ViewItemURL>http://url</ViewItemURL>
            ....
           </item> 

It should print

Element Local Name:ItemID
Text:4504216603
Element Local Name:StartTime
Text:10:00:10.000Z
Element Local Name:EndTime
Text:10:00:30.000Z
Element Local Name:ViewItemURL
Text:http://url

This code prints also root, item etc. Is it even possible, it must be I just can't google it.

XMLInputFactory inputFactory = XMLInputFactory.newInstance();
InputStream input = new FileInputStream(new File("src/main/resources/file.xml"));
XMLStreamReader xmlStreamReader = inputFactory.createXMLStreamReader(input);

while (xmlStreamReader.hasNext()) {
    int event = xmlStreamReader.next();

    if (event == XMLStreamConstants.START_ELEMENT) {
    System.out.println("Element Local Name:" + xmlStreamReader.getLocalName());
    }

    if (event == XMLStreamConstants.CHARACTERS) {
                        if(!xmlStreamReader.getText().trim().equals("")){
                        System.out.println("Text:"+xmlStreamReader.getText().trim());
                        }
                }

            }

Edit incorrect behaviour :

    Element Local Name:root
    Element Local Name:item
    Element Local Name:ItemID
    Text:4504216603
    Element Local Name:ListingDetails
    Element Local Name:StartTime
    Text:10:00:10.000Z
    Element Local Name:EndTime
    Text:10:00:30.000Z
    Element Local Name:ViewItemURL
    Text:http://url

I don't want that root and other nodes which don't have text to be printed, just the output which I wrote above. thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉态萌生 2024-09-17 20:17:06

试试这个:

while (xmlStreamReader.hasNext()) {
    int event = xmlStreamReader.next();

    if (event == XMLStreamConstants.START_ELEMENT) {
        try {
            String text = xmlStreamReader.getElementText();
            System.out.println("Element Local Name:" + xmlStreamReader.getLocalName());
            System.out.println("Text:" + text);
        } catch (XMLStreamException e) {

        }
    }

}

基于 SAX 的解决方案(有效):

public class Test extends DefaultHandler {

    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException, XMLStreamException {
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        parser.parse(new File("src/file.xml"), new Test());
    }

    private String currentName;

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        currentName = qName;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String string = new String(ch, start, length);
        if (hasText(string)) {
            System.out.println(currentName);
            System.out.println(string);
        }
    }

    private boolean hasText(String string) {
        string = string.trim();
        return string.length() > 0;
    }
}

Try this:

while (xmlStreamReader.hasNext()) {
    int event = xmlStreamReader.next();

    if (event == XMLStreamConstants.START_ELEMENT) {
        try {
            String text = xmlStreamReader.getElementText();
            System.out.println("Element Local Name:" + xmlStreamReader.getLocalName());
            System.out.println("Text:" + text);
        } catch (XMLStreamException e) {

        }
    }

}

SAX based solution (works):

public class Test extends DefaultHandler {

    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException, XMLStreamException {
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        parser.parse(new File("src/file.xml"), new Test());
    }

    private String currentName;

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        currentName = qName;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String string = new String(ch, start, length);
        if (hasText(string)) {
            System.out.println(currentName);
            System.out.println(string);
        }
    }

    private boolean hasText(String string) {
        string = string.trim();
        return string.length() > 0;
    }
}
没︽人懂的悲伤 2024-09-17 20:17:06

Stax 解决方案:

解析文档

public void parseXML(InputStream xml) {
        try {

            DOMResult result = new DOMResult();
            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
            XMLEventReader reader = xmlInputFactory.createXMLEventReader(new StreamSource(xml));
            TransformerFactory transFactory = TransformerFactory.newInstance();
            Transformer transformer = transFactory.newTransformer();
            transformer.transform(new StAXSource(reader), result);
            Document document = (Document) result.getNode();

            NodeList startlist = document.getChildNodes();

            processNodeList(startlist);

        } catch (Exception e) {
            System.err.println("Something went wrong, this might help :\n" + e.getMessage());
        }
    }

现在文档中的所有节点都在 NodeList 中,因此接下来执行此操作:

private void processNodeList(NodeList nodelist) {
        for (int i = 0; i < nodelist.getLength(); i++) {
            if (nodelist.item(i).getNodeType() == Node.ELEMENT_NODE && (hasValidAttributes(nodelist.item(i)) || hasValidText(nodelist.item(i)))) {
                getNodeNamesAndValues(nodelist.item(i));
            }
            processNodeList(nodelist.item(i).getChildNodes());
        }
    }

然后对于具有有效文本的每个元素节点,获取名称和值

public void getNodeNamesAndValues(Node n) {

        String nodeValue = null;
        String nodeName = null;

        if (hasValidText(n)) {
            while (n != null && isWhiteSpace(n.getTextContent()) == true && StringUtils.isWhitespace(n.getTextContent()) && n.getNodeType() != Node.ELEMENT_NODE) {
                n = n.getFirstChild();
            }

            nodeValue = StringUtils.strip(n.getTextContent());
            nodeName = n.getLocalName();

            System.out.println(nodeName + " " + nodeValue);

        }
    }

一堆有用的方法来检查节点:

private static boolean hasValidAttributes(Node node) {
        return (node.getAttributes().getLength() > 0);

    }

private boolean hasValidText(Node node) {
        String textValue = node.getTextContent();

        return (textValue != null && textValue != "" && isWhiteSpace(textValue) == false && !StringUtils.isWhitespace(textValue) && node.hasChildNodes());
    }

private boolean isWhiteSpace(String nodeText) {
        if (nodeText.startsWith("\r") || nodeText.startsWith("\t") || nodeText.startsWith("\n") || nodeText.startsWith(" "))
            return true;
        else
            return false;
    }

我还使用了 StringUtils,您可以通过以下方式获得:如果您使用 maven ,请将其包含在您的 pom.xml 中:

<dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.5</version>
        </dependency>

如果您正在读取大文件,则效率很低,但如果您先拆分它们,则效率不高。这就是我带来的(与谷歌)。还有更多更好的解决方案,这是我的,我是业余爱好者(目前)。

Stax solution :

Parse document

public void parseXML(InputStream xml) {
        try {

            DOMResult result = new DOMResult();
            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
            XMLEventReader reader = xmlInputFactory.createXMLEventReader(new StreamSource(xml));
            TransformerFactory transFactory = TransformerFactory.newInstance();
            Transformer transformer = transFactory.newTransformer();
            transformer.transform(new StAXSource(reader), result);
            Document document = (Document) result.getNode();

            NodeList startlist = document.getChildNodes();

            processNodeList(startlist);

        } catch (Exception e) {
            System.err.println("Something went wrong, this might help :\n" + e.getMessage());
        }
    }

Now all nodes from the document are in a NodeList so do this next :

private void processNodeList(NodeList nodelist) {
        for (int i = 0; i < nodelist.getLength(); i++) {
            if (nodelist.item(i).getNodeType() == Node.ELEMENT_NODE && (hasValidAttributes(nodelist.item(i)) || hasValidText(nodelist.item(i)))) {
                getNodeNamesAndValues(nodelist.item(i));
            }
            processNodeList(nodelist.item(i).getChildNodes());
        }
    }

Then for each element node with valid text get name and value

public void getNodeNamesAndValues(Node n) {

        String nodeValue = null;
        String nodeName = null;

        if (hasValidText(n)) {
            while (n != null && isWhiteSpace(n.getTextContent()) == true && StringUtils.isWhitespace(n.getTextContent()) && n.getNodeType() != Node.ELEMENT_NODE) {
                n = n.getFirstChild();
            }

            nodeValue = StringUtils.strip(n.getTextContent());
            nodeName = n.getLocalName();

            System.out.println(nodeName + " " + nodeValue);

        }
    }

Bunch of useful methods to check nodes :

private static boolean hasValidAttributes(Node node) {
        return (node.getAttributes().getLength() > 0);

    }

private boolean hasValidText(Node node) {
        String textValue = node.getTextContent();

        return (textValue != null && textValue != "" && isWhiteSpace(textValue) == false && !StringUtils.isWhitespace(textValue) && node.hasChildNodes());
    }

private boolean isWhiteSpace(String nodeText) {
        if (nodeText.startsWith("\r") || nodeText.startsWith("\t") || nodeText.startsWith("\n") || nodeText.startsWith(" "))
            return true;
        else
            return false;
    }

I also used StringUtils, you can get that by including this in your pom.xml if you're using maven :

<dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.5</version>
        </dependency>

This is inefficient if you're reading huge files, but not so much if you split them first. This is what I've come with(with google). There are more better solutions this is mine, I'm an amateur(for now).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文