1

我正在尝试解析来自 SOAP Web 服务的响应,但部分数据包含无效的 xmlns 元素,我认为这给我带来了无穷无尽的麻烦。

我正在使用的 XML 部分如下所示。

<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <ResponseData xmlns="http://www.example.com/WebServices/Schemas/1">
        <ResponseDataResult>
            <Messages xmlns="http://www.example.com/WebServices/Schemas/2">
                <Message>...</Message>
            </Messages>
        </ResponseDataResult>
        ...
    </ResponseData>
</soap:Body>

soap:Body 节点中的 xmlns URI 是可以的,它在 ResponseData 中是无效的,它指向一个不存在的文档。应该注意的是,网络服务不在我的控制之下,所以修复这个问题是不可能的:(。

目前,我的 Delphi (2007) 代码看起来像这样。

var l_tmp,l_tmp2,FSOAPBody:IXMLNode;

begin
    ...

    FSOAPBody := FSOAPEnvelope.ChildNodes.FindNode('Body','http://schemas.xmlsoap.org/soap/envelope/');
    //returns the xml above.
    if (FSOAPBody = nil) then exit;

    l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData','');
    if (l_tmp = nil) or (not l_tmp.HasChildNodes) then exit;

    l_tmp2 := l_tmp.ChildNodes.FindNode('ResponseDataResult','');

    ...
end;

在上面的代码中,我不得不将空白命名空间 url 添加到FindNode('ResponseData','')代码中,因为没有它,它不会找到任何东西并返回 nil,但是它会返回预期的 XML。

问题是下一个查找节点ChildNodes.FindNode('ResponseDataResult','')

我怀疑这是由于缺少命名空间,所以我试图删除它,但收到更多错误,说它是一个只读属性。

不管有没有 NS,是否有删除 xmlns 属性或选择节点?还是我要解决这个问题?

4

1 回答 1

2

It is not expected that all namespace URIs refer to actual resources. They are used primarily as unique identifiers so XML from multiple sources can use the same names without interfering with each other. They are not required to point to the schema that describes the valid element and attribute values for the namespace; XML doesn't even require that such a schema exist.

If you want to search for elements without regard for namespace, then call the one-argument version of FindNode.

l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData');

The two-argument version requires a namespace, and when you specify an empty string, it means you're requesting only nodes that have empty namespaces. Since you apparently know what the namespace is, you could call the two-argument version anyway, just like you used it to get the body element:

l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData',
           'http://www.example.com/WebServices/Schemas/1');
于 2009-05-06T14:10:33.147 回答