【问题标题】:Java XML Parser -- how to collect or count a certain tagJava XML Parser——如何收集或统计某个标签
【发布时间】:2014-10-29 12:21:09
【问题描述】:

我正在尝试解析一个简单的 XML 文件。如果我有以下 XML 字符串,

<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

我只想从&lt;body&gt;...&lt;/body&gt; 中提取字符串。我正在使用 SAXParser 和一个默认处理程序。通过在 DefaultHandler 的“characters”方法中显式添加打印语句,我成功打印出标签中的所有字符串。但我不确定在哪里调用这个字符方法,以及如何控制它。

我知道如何在 startElement 中发现某个标签,但是如何从 startElement 中的标签中提取字符串?

【问题讨论】:

  • DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();文档 doc = db.parse(new ByteArrayInputStream(xml.getBytes())); String bodyText = doc.getElementsByTagName("body").item(0).getTextContent();
  • 尝试使用 DOM 解析器。在这种情况下更容易。

标签: java xml parsing sax


【解决方案1】:

根据 SAX,默认处理程序文档,

public void characters(char[] ch,
                       int start,
                       int length)
                throws SAXException

解析器会调用这个方法来报告每个字符块 数据。 SAX 解析器可以在单个文件中返回所有连续的字符数据 块,或者他们可能将其分成几个块;然而,所有的 任何单个事件中的角色必须来自同一个外部实体 以便定位器提供有用的信息。

因此解析器可能会为元素中的特定文本调用 characters 方法一次或多次,说“这个周末别忘了我!”,直到读取整个文本。

注意:

应用程序不得尝试从 指定范围。

以下代码展示了如何收集单个 XML 元素中的文本。

boolean isTagInScope = false;
StringBuilder elementContent = new StringBuilder();
public void startElement(String namespaceURI, String lName, String qName,
Attributes attributes) throws SAXException 
{
 isTagInScope = true;
}

public void endElement(String namespaceURI, String sName, String qName)
throws SAXException  throws SAXException {
 isTagInScope = false;
}

public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
if(isTagInScope)
{
 String content = new String(arg0, arg1, arg2);
 elementContent.append(content);
}
}

“elementContent”变量将保存元素开始和结束标记之间的全部内容。

【讨论】:

    【解决方案2】:

    您可以使用 Java SE 中的 javax.xml.xpath API 来提取元素的文本。

    演示代码

    import javax.xml.xpath.*;
    import org.xml.sax.InputSource;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            InputSource inputSource = new InputSource("input.xml");
            XPath xPath = XPathFactory.newInstance().newXPath();
            String text = xPath.evaluate("/note/body", inputSource);
            System.out.println(text);
        }
    
    }
    

    输出

    Don't forget me this weekend!
    

    【讨论】:

      【解决方案3】:

      您可以设置一个标志,或使用一个枚举来指示您在开始时所在的元素,并在 characters 方法中相应地解释它。

      我做的一件事是有一组与标签相对应的匿名类。在开始时,我标记我所在的元素,以便我可以使用正确的匿名类根据元素对字符执行我想要的操作(例如错误处理、日期格式,或者在您的情况下打印相关的字符到标签)。我将那些匿名内部类存储在以标签为键的映射中。所以在角色中,我知道我在哪个元素中,如果我有合适的处理程序,我会处理它。

      这种方法在将 xml 输入转换为类时非常有用。

      【讨论】:

        【解决方案4】:

        根据@BatScream 的见解修改

        事情是当你得到标签'body'的开始时设置一个标志,然后在characters方法中如果标志是真的你有它。

        public class NoteHandler extends DefaultHandler {
            private static final STRING TAG_BODY = "body";
            private boolean bodyFlag = false;
            private StringBuilder body = new StringBuilder();
        
            public void startDocument() throws SAXException {}
        
            public void endDocument() throws SAXException {}
        
            public void startElement(String uri, String localName, tring qName, Attributes attributes) throws SAXException {
                bodyFlag = TAG_BODY.equals(qName); // true when body tag
            }
        
            public void endElement(String uri, String localName, String qName) throws SAXException {
                if(bodyFlag) {
                    bodyFlag = false;
                    System.out.println(body.toString());
                }
            }
        
            public void characters(char ch[], int start, int length) throws SAXException {
                if(bodyFlag) {
                    body.append(new String(ch, start, length);
                }
            }
        }
        

        【讨论】:

        • 如果多次调用characters方法,会丢失部分内容。
        猜你喜欢
        • 1970-01-01
        • 2023-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-23
        • 2010-11-08
        • 2011-03-11
        • 2022-07-10
        相关资源
        最近更新 更多