如何在Java中获取包含其他嵌入式XML标记的<tagname>的内容?</tagname>

时间:2011-10-02 07:23:56

标签: java xml dom xml-parsing sax

我有一个包含HTML标记的XML文档:

<chapter>
      <h1>title of content</h1>
      <p> my paragraph ... </p>
 </chapter>

我需要获取<chapter>标记的内容,我的输出将是:

      <h1>title of content</h1>
      <p> my paragraph ... </p>

我的问题类似于这篇文章:How parse XML to get one tag and save another tag inside

但我需要在Java中使用SAX或DOM或......?

来实现它

我在这篇文章中找到了一个使用SAX的解决方案:SAX Parser : Retrieving HTML tags from XML但它非常错误,并且无法处理大量的XML数据。

更新

我的SAX实施: 在某些情况下,它会抛出异常:java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:-4029

public class MyXMLHandler extends DefaultHandler {

private boolean tagFlag = false;

private char[] temp;
String insideTag;
private int startPosition;
private int endPosition;
private String tag;

public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {


    if (qName.equalsIgnoreCase(tag)) {
        tagFlag = true;
    }

}

public void endElement(String uri, String localName, String qName)
        throws SAXException {

    if (qName.equalsIgnoreCase(tag)) {

        insideTag = new String(temp, startPosition, endPosition - startPosition);
        tagFlag = false;
    }

}

public void characters(char ch[], int start, int length)
        throws SAXException {
    temp = ch;
    if (tagFlag) {
        startPosition = start;
        tagFlag = false;
    }
    endPosition = start + length;
}

public String getInsideTag(String tag) {
    this.tag = tag;
    return insideTag;
}

}

更新2 :(使用StringBuilder)

我通过StringBuilder以这种方式累积了字符:

public class MyXMLHandler extends DefaultHandler {

private boolean tagFlag = false;

private char[] temp;
String insideTag;
private String tag;
private StringBuilder builder;

public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {

    if (qName.equalsIgnoreCase(tag)) {
        builder = new StringBuilder();
        tagFlag = true;
    }

}

public void endElement(String uri, String localName, String qName)
        throws SAXException {

    if (qName.equalsIgnoreCase(tag)) {
        insideTag = builder.toString();
        tagFlag = false;
    }
}

public void characters(char ch[], int start, int length)
        throws SAXException {
    if (tagFlag) {
        builder.append(ch, start, length);
    }
}

public String getInsideTag(String tag) {
    this.tag = tag;
    return insideTag;
}

}

builder.append(ch, start, length);不会在缓冲区中添加<EmbeddedTag atr="..."></EmbeddedTag>等开始标记。本代码打印输出:

      title of content
      my paragraph ... 

而不是预期的输出:

      <h1>title of content</h1>
      <p> my paragraph ... </p>

更新3:

最后我实现了解析器处理程序:

 public class MyXMLHandler extends DefaultHandler {

private boolean tagFlag = false;
private String insideTag;
private String tag;
private StringBuilder builder;

public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {

    if (qName.equalsIgnoreCase(tag)) {
        builder = new StringBuilder();
        tagFlag = true;
    }

    if (tagFlag) {
        builder.append("<" + qName);
         for (int i = 0; i < attributes.getLength(); i++) {
         builder.append(" " + attributes.getLocalName(i) + "=\"" +
         attributes.getValue(i) + "\"");
         }
         builder.append(">");
    }
}

public void endElement(String uri, String localName, String qName)
        throws SAXException {

    if (tagFlag) {
        builder.append("</" + qName + ">");
    }

    if (qName.equalsIgnoreCase(tag)) {
        insideTag = builder.toString();                     
        tagFlag = false;
    }
    System.out.println("End Element :" + qName);

}

public void characters(char ch[], int start, int length)
        throws SAXException {
    temp = ch;

    if (tagFlag) {
        builder.append(ch, start, length);
    }
}

public String getInsideTag(String tag) {
    this.tag = tag;
    return insideTag;
}

}

2 个答案:

答案 0 :(得分:0)

您的代码的问题在于您尝试记住通过characters方法传递给您的字符串的开始和结束位置。在抛出的异常中看到的是内部标记的结果,该标记在字符缓冲区的末尾附近开始,并在下一个字符缓冲区的开头附近结束。

使用sax时,您需要在提供字符时复制它们,或者在您需要时可以清除它们占用的临时缓冲区。

最好的办法是不要记住缓冲区中的位置,而是要在StringBuilder中创建一个新的startElement并添加字符,然后在{{{{}}中获取完整的字符串。 1}}。

答案 1 :(得分:0)

尝试使用Digester,我在几年前使用它,版本1.5,它只是像你一样为xml创建映射。简单article如何使用Digester,但它适用于1.5版本,目前有3.0版本我觉得上一版本包含很多新功能......