当前位置: 首页 > 面试题库 >

Java DOM转换和解析具有无效XML字符的任意字符串?

贺卜霸
2023-03-14
问题内容

首先,我想提一下,这不是“
如何解析无效(格式错误/格式不正确)的XML”的副本?因为我没有给定的无效(或格式不正确)的XML文件,而是给定的任意Java
String,它可能包含也可能不包含无效的XML字符。我想创建一个Document包含Text具有给定节点的DOM
String,然后将其转换为文件。当文件解析为DOM时,Document我想获得一个String等于初始给定值的String。我使用创建Text节点,org.w3c.dom.Document#createTextNode(String data)并使用获取字符串org.w3c.dom.Node#getTextContent()

如您在http://codingdict.com/questions/110317中所见,TextXML文件中的节点存在一些无效字符。实际上,Text节点有两种不同类型的“无效”字符。有预定义的实体,例如"&'<>其自动地由DOM
API与逃脱&quot;&amp;&apos;&lt;&gt;在生成的文件是由DOM
API而复当文件被解析。现在的问题是,其他无效字符(例如'\u0000'或)则不是这种情况'\uffff'。解析文件时会发生异常,因为'\u0000''\uffff'是无效字符。

可能我必须实现一种以给定String的方式对那些字符进行转义的方法,然后再将其提交给DOM
API,并在稍后得到String回复时撤消该操作,对吗?有一个更好的方法吗?过去有人实施过这些或类似方法吗?

编辑:
这个问题被标记为Java中编码XML文本数据的最佳方法的重复吗?。我现在已经阅读了所有答案,但是没有一个能解决我的问题。所有答案都表明:

  • 使用XML库,如DOM API,我已经这样做了,没有这些库,除了实际上是替换无效字符"&'<>和几个。
  • 替换所有无效字符"&#number;"将导致无效字符的异常,例如"&#0;"在分析文件时。
  • 将第三方库与XML编码方法一起使用,它们不支持诸如"&#0;"(在某些库中被跳过)之类的非法字符。
  • 使用也不支持无效字符的CDATA部分。

问题答案:

正如@VGR和@kjhughes在问题下方的注释中指出的那样,Base64确实是我问题的可能答案。现在,我确实有一个基于转义的问题的进一步解决方案。我已经写了2种功能escapeInvalidXmlCharacters(String string),并unescapeInvalidXmlCharacters(String string)可以通过以下方式使用。

    String string = "text#text##text#0;text" + '\u0000' + "text<text&text#";
    Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    Element element = document.createElement("element");
    element.appendChild(document.createTextNode(escapeInvalidXmlCharacters(string)));
    document.appendChild(element);
    TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(new File("test.xml")));
    // creates <?xml version="1.0" encoding="UTF-8" standalone="no"?><element>text##text####text##0;text#0;text&lt;text&amp;text##</element>
    document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("test.xml"));
    System.out.println(unescapeInvalidXmlCharacters(document.getDocumentElement().getTextContent()).equals(string));
    // prints true

escapeInvalidXmlCharacters(String string)unescapeInvalidXmlCharacters(String string)

/**
 * Escapes invalid XML Unicode code points in a <code>{@link String}</code>. The
 * DOM API already escapes predefined entities, such as {@code "}, {@code &},
 * {@code '}, {@code <} and {@code >} for
 * <code>{@link org.w3c.dom.Text Text}</code> nodes. Therefore, these Unicode
 * code points are ignored by this function. However, there are some other
 * invalid XML Unicode code points, such as {@code '\u0000'}, which are even
 * invalid in their escaped form, such as {@code "&#0;"}.
 * <p>
 * This function replaces all {@code '#'} by {@code "##"} and all Unicode code
 * points which are not in the ranges #x9 | #xA | #xD | [#x20-#xD7FF] |
 * [#xE000-#xFFFD] | [#x10000-#x10FFFF] by the <code>{@link String}</code>
 * {@code "#c;"}, where <code>c</code> is the Unicode code point.
 * 
 * @param string the <code>{@link String}</code> to be escaped
 * @return the escaped <code>{@link String}</code>
 * @see <code>{@link #unescapeInvalidXmlCharacters(String)}</code>
 */
public static String escapeInvalidXmlCharacters(String string) {
    StringBuilder stringBuilder = new StringBuilder();

    for (int i = 0, codePoint = 0; i < string.length(); i += Character.charCount(codePoint)) {
        codePoint = string.codePointAt(i);

        if (codePoint == '#') {
            stringBuilder.append("##");
        } else if (codePoint == 0x9 || codePoint == 0xA || codePoint == 0xD || codePoint >= 0x20 && codePoint <= 0xD7FF || codePoint >= 0xE000 && codePoint <= 0xFFFD || codePoint >= 0x10000 && codePoint <= 0x10FFFF) {
            stringBuilder.appendCodePoint(codePoint);
        } else {
            stringBuilder.append("#" + codePoint + ";");
        }
    }

    return stringBuilder.toString();
}

/**
 * Unescapes invalid XML Unicode code points in a <code>{@link String}</code>.
 * Makes <code>{@link #escapeInvalidXmlCharacters(String)}</code> undone.
 * 
 * @param string the <code>{@link String}</code> to be unescaped
 * @return the unescaped <code>{@link String}</code>
 * @see <code>{@link #escapeInvalidXmlCharacters(String)}</code>
 */
public static String unescapeInvalidXmlCharacters(String string) {
    StringBuilder stringBuilder = new StringBuilder();
    boolean escaped = false;

    for (int i = 0, codePoint = 0; i < string.length(); i += Character.charCount(codePoint)) {
        codePoint = string.codePointAt(i);

        if (escaped) {
            stringBuilder.appendCodePoint(codePoint);
            escaped = false;
        } else if (codePoint == '#') {
            StringBuilder intBuilder = new StringBuilder();
            int j;

            for (j = i + 1; j < string.length(); j += Character.charCount(codePoint)) {
                codePoint = string.codePointAt(j);

                if (codePoint == ';') {
                    escaped = true;
                    break;
                }

                if (codePoint >= 48 && codePoint <= 57) {
                    intBuilder.appendCodePoint(codePoint);
                } else {
                    break;
                }
            }

            if (escaped) {
                try {
                    codePoint = Integer.parseInt(intBuilder.toString());
                    stringBuilder.appendCodePoint(codePoint);
                    escaped = false;
                    i = j;
                } catch (IllegalArgumentException e) {
                    codePoint = '#';
                    escaped = true;
                }
            } else {
                codePoint = '#';
                escaped = true;
            }
        } else {
            stringBuilder.appendCodePoint(codePoint);
        }
    }

    return stringBuilder.toString();
}

请注意,这些功能可能效率很低,可以用更好的方式编写。随时发布建议以改进注释中的代码。



 类似资料:
  • 总之,我正在尝试解析中的xml。但是XMLSpy告诉我xml的格式不好。 我相信这xml中包含了一些无效字符()。因为如果我把它拿走。XMLSpy的验证已通过。我认为UTF-8编码不允许这种字符。但是如果我真的想加入这种角色呢。我应该应用哪种编码?谢谢

  • 我将XML作为字符串传递给一个方法,并再次将其转换为XML来完成我的工作。 其正常工作正常,但当出现特殊字符时,如<代码> 我的XML字符串: 我的代码是: 错误: “=”是意外标记。预期标记为“;”。第1行,位置150。 完全错误为: 系统Xml。XmlException未由用户代码处理HResult=-2146232000消息=“=”是意外令牌。预期标记为“;”。第1行,位置150。源=系统。

  • 问题内容: 您好,我正在从Web服务获取一个字符串。 我需要解析此字符串并获取错误消息中的文本? 我的字符串如下所示: 仅分析字符串还是将其转换为xml然后进行分析是否更好? 问题答案: 我将使用Java的XML文档库。有点混乱,但是可以。

  • 问题内容: 您如何解析存储在Java字符串对象中的xml? Java的XMLReader仅从URI或输入流中解析XML文档。无法从包含xml数据的字符串进行解析? 现在,我有以下内容: 在我的处理程序上,我有这个: 提前致谢 问题答案: 该SAXParser的可以读取的的InputSource。 一个 InputSource的 可以采取 读者 在其构造 因此,您可以通过StringReader来解

  • 我想要一个带有ANTLR的规则,将任何字符解析为数字、字符串特殊('@space)等,直到单词FOOTER(不包括) 我要解析的文本是这样的 我尝试使用此代码:在词法分析器中。 在解析器中。 但它不起作用。

  • 问题内容: 我有一个无效的json字符串,如下所示, 我尝试使用JSON.parse将其转换为对象。但是,这不是有效的json字符串。是否有任何函数可以将这种无效格式转换为有效的json字符串或直接转换为对象? 问题答案: 如果您的示例语法与真实JSON相同,则JSONLint表示您需要对名称和值使用双引号。 仅在这种情况下,请使用以下替换调用: 但是,您首先应该尝试使用有效的Json。