【问题标题】:How to get content of <tagname> that contains other embedded XML tag in Java?如何在 Java 中获取包含其他嵌入式 XML 标记的 <tagname> 的内容?
【发布时间】:2011-11-29 07:39:52
【问题描述】:

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

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

我需要获取&lt;chapter&gt; 标签的内容,我的输出将是:

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

我的问题和这个帖子类似:How parse XML to get one tag and save another tag inside

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

我在这篇文章中找到了一个使用 SAX 的解决方案:SAX Parser : Retrieving HTML tags from XML,但它有很多错误,并且不适用于大量 XML 数据。

更新:

我的 SAX 实现: 在某些情况下,它会抛出异常:java.lang.StringIndexOutOfBoundsException: String index out of range: -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); 不会在缓冲区中附加像&lt;EmbeddedTag atr="..."&gt;&lt;/EmbeddedTag&gt; 这样的开始标记。此代码打印输出:

      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;
}

}

【问题讨论】:

  • 您需要更好地定义输入 XML,特别是尽可能地定义所需的输出,因为您的帖子根本不清楚。您似乎希望保留一些标签,但其他标签不保留。此外,如果 XML 非常大,则 DOM 可能不可行,因为 DOM 要求在执行分析之前加载整个文档模型。其他选项是 SAX 和 StAX。
  • 感谢您编辑我糟糕的文章。是的,我需要获取 标签的内容。我用我的 SAX 实现更新了我的帖子,但在某些情况下它不起作用。你能帮我解决我更新的问题吗?

标签: java xml dom xml-parsing sax


【解决方案1】:

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

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

最好不要记住缓冲区中的位置,而是在startElement 中创建一个新的StringBuilder 并将字符添加到其中,然后从endElement 中的构建器中获取完整的字符串。

【讨论】:

  • 我已经通过向 StringBuilder 添加字符来更改我的代码,但问题是在 characters() 回调中我无法访问标记名的开头和标记名的结尾!所以我必须像这样更改 StringBuilder 参数: handler.append(ch, start - startTag.length, length + endTag.length) 。我应该怎么做?
  • 您可以在 start- 和 endElement 方法中添加开始和结束标记。
【解决方案2】:

尝试使用Digester,我多年前就使用过它,1.5 版,它只是为像你这样的 xml 创建映射。只是简单article如何使用 Digester,但它是针对 1.5 版本的,目前有 3.0 我认为最后一个版本包含很多新功能...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    相关资源
    最近更新 更多