You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决SAXParseException:XML文档结构必须在同一实体中首尾匹配

XML解析问题:获取字段值时遇到SAXParseException错误

问题详情

我在解析XML获取字段值时遇到异常,XML示例如下:

<?xml version="1.0" encoding="UTF-8"?><Document xmlns="urn:iso:std:iso:20022:tech:xsd:notificationName">
  <Ntfctn>
    <MsgHdr>
      <MsgId>47e22e35-6866-46f0-bc5d-8b5bb6afaba7</MsgId>
      <CreDt>2023-07-03T20:41:20Z</CreDt>
      <Fr>66666666-6666-4666-8666-666666666666</Fr>
      <To>93216692-7432-444d-88a1-18297159a92a</To>
      <OprId>4e8cf5f6-c6e1-4314-b043-65dfe13ab2fa</OprId>
    </MsgHdr>
    <OprInfAndSts>
      <OprInf>
        <DCXchgOprInf>
          <XchgOprAmt>
            <TtlAmt Ccy="RUB">147.71</TtlAmt>
          </XchgOprAmt>
          <DgtlCcyTrfData>
            <DCBuyr>
              <Wllt>
                <Id>93216692-7432-444d-88a1-18297159a92a</Id>
                <Bal>
                  <TtlAmt Ccy="RUB">13122.60</TtlAmt>
                </Bal>
              </Wllt>
            </DCBuyr>
          </DgtlCcyTrfData>
          <SttlmDtTm>2023-07-03T20:41:20Z</SttlmDtTm>
        </DCXchgOprInf>
      </OprInf>
    </OprInfAndSts>
  </Ntfctn>
</Document>

我编写的字段获取方法:

public String getFieldValue(String xml, String tagName, String tagValue) {
            xml = xml.trim().replaceFirst("<?","<");
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            Document parse = documentBuilderFactory.newDocumentBuilder().parse(byteArrayInputStream);
            NodeList nodeList = parse.getElementsByTagName(tagName);
            Node item = nodeList.item(0);
            return item.getTextContent();
    }

此前遇到"content is not allowed in prolog"错误,添加trim()和replaceFirst()后解决,但现在调用方法时触发SAXParseException,提示"XML document structures must start and end within the same entity",不知道如何修复。


修复方案

1. 移除错误的XML声明修改操作

你的replaceFirst("<?","<")直接破坏了XML声明的合法性,把<?xml ...?>改成了<xml ...?>,导致解析器无法识别完整的文档结构,这是当前错误的核心原因。之前的prolog错误大概率是XML开头存在隐藏的UTF-8 BOM字符,不该用粗暴替换的方式解决。

2. 正确处理开头的隐藏字符

替换掉错误的replaceFirst,改用安全方式过滤可能的BOM和空白:

if (xml.startsWith("\uFEFF")) {
    xml = xml.substring(1);
}
xml = xml.trim();

3. 处理XML命名空间

你的XML带有命名空间urn:iso:std:iso:20022:tech:xsd:notificationName,默认的getElementsByTagName无法识别带命名空间的元素,需要启用命名空间支持并使用getElementsByTagNameNS:

public String getFieldValue(String xml, String namespaceUri, String tagName) {
    // 处理BOM和开头空白
    if (xml.startsWith("\uFEFF")) {
        xml = xml.substring(1);
    }
    xml = xml.trim();

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    // 启用命名空间支持
    documentBuilderFactory.setNamespaceAware(true);
    
    try {
        Document parse = documentBuilderFactory.newDocumentBuilder().parse(byteArrayInputStream);
        NodeList nodeList = parse.getElementsByTagNameNS(namespaceUri, tagName);
        if (nodeList.getLength() > 0) {
            return nodeList.item(0).getTextContent();
        }
        return null;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

调用时传入命名空间参数:

String oprId = getFieldValue(xmlContent, "urn:iso:std:iso:20022:tech:xsd:notificationName", "OprId");

4. 额外注意事项

  • 不要手动修改XML的结构或声明,极易引入语法错误
  • 解析带命名空间的XML时,必须启用命名空间支持
  • 解析过程中捕获异常并打印堆栈信息,便于排查问题

内容的提问来源于stack exchange,提问作者Ruslan Fazylyanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:32:49