xerces_3_1 能够在评论和处理说明中创建无效的 xml

xerces_3_1 is able to create invalid xml at comments & processing instructions

我在使用 xerces-dom 库时遇到问题:

当您向 xml-树添加评论时,例如:

DOMDocument* doc = impl->createDocument(0, L"root", 0);
DOMElement* root = doc->getDocumentElement();
DOMComment* com1 = doc->createComment(L"SetA -- DataA");
DOMComment* com2 = doc->createComment(L"SetB -- DataB");
doc->insertBefore(com1, root);
doc->insertBefore(com2, root);

这将创建以下 xml-树:

<?xml version="1.0" encoding="UTF-8" standalone="false"?>
<!--SetA -- DataA-->
<!--SetB -- DataB-->
<root/>

确实无效xml.


同样可以通过使用?>作为数据来处理指令:

DOMProcessingInstruction procInstr = doc->createProcessingInstruction(L"target", L"?>");

我的问题:

有什么方法可以配置 xerces 不创建此类评论,还是我必须自己检查这些内容?

还有我的另一个问题:为什么不能总是转义像 <>&'" 这样的字符,甚至在注释和处理指令中,以避免此类问题?

DOM文档不是 XML 文档。它应该代表一个,但可以想象一个有效的 DOM 可能无法序列化为一个有效的 XML 文档(相反的情况应该不太可能)。确实这似乎是这里的情况:

Level 1 和 Level2 两个规范都没有提到这个,但是 Level 3 DOM specification 添加了关于 DOM评论界面的这句话:

No lexical check is done on the content of a comment and it is therefore possible to have the character sequence "--" (double-hyphen) in the content, which is illegal in a comment per section 2.5 of [XML 1.0]. The presence of this character sequence must generate a fatal error during serialization.

所以 Xerces 在 DOM 级别 3 规范内运行,即使它接受其中带有 '--' 的注释,只要它在你去序列化它时爆炸。

情况不太好,但这是有道理的,因为 DOM 最初是为了表示 XML 已读入的文档,而不是创建新文档。所以它可以代表什么是自由的。适合阅读 - DOM评论可以代表 XML 文档可以代表的任何内容(甚至更多),但有点烦人的是当您 createComment().

检查 DOMDocumentImpl.cpp 我们看到:

DOMComment *DOMDocumentImpl::createComment(const XMLCh *data)
{
    return new (this, DOMMemoryManager::COMMENT_OBJECT) DOMCommentImpl(this, data);
}

而在 DOMCommentImpl.cpp 中我们只有:

DOMCommentImpl::DOMCommentImpl(DOMDocument *ownerDoc, const XMLCh *dat)
    : fNode(ownerDoc),  fCharacterData(ownerDoc, dat)
{
    fNode.setIsLeafNode(true);
}

最后我们在 DOMCharacterDataImpl.cpp 中看到没有预先验证的机会 - 它只是保存用户提供的字符串而不检查它。

DOMCharacterDataImpl::DOMCharacterDataImpl(DOMDocument *doc, const XMLCh *dat)
{
    fDoc = (DOMDocumentImpl*)doc;

    XMLSize_t len=XMLString::stringLen(dat);
    fDataBuf = fDoc->popBuffer(len+1);
    if (!fDataBuf)
        fDataBuf = new (fDoc) DOMBuffer(fDoc, len+15);
    fDataBuf->set(dat, len);
}

可悲的是,没有 Xerces 没有一个选项,甚至没有一个很好的钩子来为你检查这个。 而且因为 3 级规范似乎要求 "No lexical check is done" , 添加一个可能是不合法的。

第二个问题的答案更容易回答:因为这就是他们想要的定义它的方式。参见 XML 1.1 spec 例如:

Comments
[15]    Comment    ::=      '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'

PI 也类似。

语法根本不允许转义。似乎是对的:巴洛克风格 and broke.

也许有一种方法可以捕获序列化或规范化的错误,但我无法确认 Xerces 3.1 是否可以。为了安全起见,我认为最好的方法是在创建节点之前包装 createComment() 并检查它,或者遍历树并自己检查它。