Delphi - inválido namespace URI em IXMLNode
-
06-07-2019 - |
Pergunta
Eu estou tentando analisar uma resposta de um serviço web SOAP, mas parte dos dados tem um elemento xmlns inválido e eu acho que está me causando um problema sem fim.
A parte do XML que eu estou trabalhando com é a seguinte.
<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>
Os xmlns URI no sabão: nó corpo é OK, é o um em responseData que é inválido, ele aponta para um documento existente nenhum. Deve-se notar que o serviço web não está sob meu controle para fixar isso está fora de questão:. (
minha Delphi (2007) Código do olhar, no momento, algo como isto.
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;
No código acima, eu tive que adicionar o URL namespace em branco para o código FindNode('ResponseData','')
como sem ele, não vai encontrar nada e retorna nil, com ele no entanto, reutrns o XML esperado.
O problema é que o nó próximo find (ChildNodes.FindNode('ResponseDataResult','')
) levanta uma violação de acesso ao tentar acessar os ChildNodes de l_tmp, eu posso olhar para o xml usando l_tmp.xml e ver que ele é o XML que eu esperaria.
Eu suspeito que isso é devido ao namespace faltando, então eu tentei removê-lo, mas obter mais erros dizendo que é um atributo somente leitura.
Existe uma maneira de remover o atributo xmlns ou selecionar nós, independentemente de haver NS? ou eu vou sobre esta errado?
Solução
É não se espera que todos os URIs do namespace referem a recursos reais. Eles são usados ??principalmente como identificadores únicos de modo XML a partir de várias fontes podem usar os mesmos nomes, sem interferir uns com os outros. Eles não são necessários para apontar para o esquema que descreve os valores de elementos e atributos válidos para o namespace; XML nem sequer exigem que as houver esquema a.
Se você quiser procurar por elementos sem levar em conta namespace, em seguida, chamar a versão de um argumento de FindNode
.
l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData');
A versão de dois argumentos requer um espaço de nomes, e quando você especificar uma cadeia vazia, isso significa que você está solicitando apenas nós que têm namespaces vazios. Desde que você parece saber o que o namespace seja, você poderia chamar a versão de dois argumentos de qualquer maneira, assim como você usou para obter o elemento do corpo:
l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData',
'http://www.example.com/WebServices/Schemas/1');