Repository navigation
Home > XML
Important
Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.
Nível: intermediário
Em uma frase: o RAL 2.0 tem um leitor e um documento XML próprios, em Pascal puro, iguais em todos os compiladores e plataformas - é o que o Storage XML e o SOAP usam, e você pode usar direto.
Você vai precisar: o pacote RALModuleXMLPackage (units RALXMLReader,
RALXMLWriter, RALXML; RALXMLC14N para a forma canônica).
Os métodos devolvem o próprio nó, para encadear:
uses RALXML;
Doc := TRALXMLDocument.Create;
try
Doc.Indent := True;
Doc.CreateRoot('pedido')
.AddAttribute('numero', '42')
.AddChild('cliente').WithText('Maria');
Doc.Root.AddChild('total').WithValue(19.9);
Doc.Root.AddChild('emissao').WithDateTime(Now);
Memo1.Text := Doc.SaveToString;
finally
Doc.Free;
end;| Para | Use |
|---|---|
| filhos e atributos |
AddChild, AddAttribute, AddNamespace
|
| texto |
WithText, WithCData, AddText, AddComment, AddProcessingInstruction
|
| valores tipados |
WithValue (inteiro, double, boolean), WithDateTime (ISO 8601), WithBCD (decimal exato), WithBase64 (bytes) |
| um fragmento pronto | AddXML('<a>1</a>') |
| um dataset |
AppendDataSet(Query1, xtDBWare) (formatos) |
Doc.LoadFromString(Texto); // ou LoadFromFile, LoadFromStream
Cliente := Doc.GetText('/pedido/cliente');
Total := Doc.GetNode('/pedido/total').AsFloat;
Numero := Doc.Root.Attribute('numero');| Para | Use |
|---|---|
| um filho |
Child('nome') (com prefixo, ou só o nome local), ChildNS(uri, nome)
|
| percorrer |
FirstElement/NextElement, FirstChild/NextSibling, Children[i]
|
| atributos |
Attribute, AttributeNS, HasAttribute, Attributes[nome]
|
| valores |
Text, InnerText, AsString, AsInteger, AsInt64, AsFloat, AsBoolean, AsDateTime, AsBCD, AsBase64
|
| caminhos |
GetNode, GetNodes, GetText, GetAttribute
|
AsFloat, AsDateTime e os outros leem o formato do XML (ponto decimal, ISO
8601) seja qual for a configuração regional da máquina.
Um subconjunto do XPath:
| Caminho | Seleciona |
|---|---|
/a/b |
b filho da raiz a
|
a/b[2] |
o segundo b
|
//c |
todo c, em qualquer nível |
item[@id='7'] |
o item com o atributo id igual a 7 |
a/* |
todos os filhos de a
|
a/b/@x |
o atributo x (em GetText e GetAttribute) |
a.b.c |
a forma com pontos, de quem vem do xmlpascal |
Os nomes casam pelo nome qualificado ou, sem prefixo no caminho, pelo nome local.
Lê UTF-8, UTF-16 (com BOM ou declarado), ISO-8859-1, Windows-1252 e US-ASCII,
pela BOM, pela declaração encoding ou pelo charset do Content-Type (que
ganha da declaração). Grava sempre UTF-8.
O leitor segue o XML 1.0 e o Namespaces 1.0, e recusa com ERALXMLError
(linha e coluna) o que não está bem formado. Os limites vêm de Options
(TRALXMLReaderOptions):
| Opção | Padrão |
|---|---|
MaxDepth |
256 níveis |
MaxAttributes |
256 por elemento |
MaxNameLength |
1024 |
MaxEntityDepth |
8 entidades uma dentro da outra |
MaxEntityExpansion |
65 536 bytes produzidos por entidades no documento inteiro |
ProcessInternalEntities |
True: entidades do DOCTYPE são expandidas, dentro dos limites |
OnResolveEntity |
entidade externa: só é lida se você resolver aqui; sem o evento, nunca |
Com isso a "bomba de bilhões de risadas" para no limite, e o XXE (ler arquivo
ou URL por entidade externa) não acontece sem você pedir. No SOAP
o DOCTYPE é recusado de vez.
Dois XML iguais para quem lê podem diferir em bytes: aspas simples ou duplas,
ordem dos atributos, <a/> ou <a></a>, namespaces repetidos. A forma
canônica escreve um jeito só, e é o que se assina ou se compara por hash
(assinatura XML, WS-Security). RALXMLC14N faz a Canonical XML 1.0 (RFC 3076)
e a exclusiva, com e sem comentários:
uses RALXML, RALXMLC14N;
Doc := TRALXMLDocument.Create;
Doc.PreserveWhitespace := True; // os brancos entre elementos fazem parte
Doc.LoadFromString(Texto);
Bytes := RALXMLCanonicalize(Doc.DocumentNode); // documento inteiro, 1.0
Corpo := RALXMLCanonicalize(Doc.GetNode('//Body'), xcmExclusive); // uma subárvore, exclusiva| Escolha | O que muda |
|---|---|
xcmInclusive |
C14N 1.0: a subárvore leva todos os namespaces em escopo e os xml:* (lang, space, base) dos ancestrais |
xcmExclusive |
só os namespaces que a subárvore usa: o trecho assinado não muda quando é posto em outro envelope |
AWithComments |
mantém os comentários (os algoritmos #WithComments) |
AInclusivePrefixes |
na exclusiva, prefixos tratados como na 1.0 ('ds #default': a PrefixList do InclusiveNamespaces) |
TRALXMLCanonicalizer.SetAlgorithm aceita o URI do algoritmo que vem num
documento assinado (RALC14NInclusive, RALC14NExclusive e os ...Comments).
A saída é UTF-8, sem declaração XML nem DOCTYPE; os atributos com valor padrão
do DOCTYPE e as entidades já vêm expandidos pelo leitor.
Note
O documento precisa ser lido com PreserveWhitespace := True: sem isso, o
texto só de brancos entre elementos já foi descartado e a forma canônica sai
diferente da de quem assinou.
Para documentos grandes, TRALXMLReader lê token a token sem montar a árvore:
R := TRALXMLReader.Create;
try
R.SetInputStream(Arquivo);
while R.Read do
if (R.Token = xtkStartElement) and (R.LocalName = 'item') then
Processa(R.AttributeValue('id'));
finally
R.Free;
end;Começar
Servidor
- Rotas e parâmetros
- Rotas avançadas: tipos, grupos, versões 🚧
- Ler o pedido e responder
- Objetos no corpo 🚧
- Resposta em fluxo 🚧
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- Swagger e Postman
- Servidor SOAP 🚧
- WS-Security 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
- Testes em memória 🚧
MQTT 🚧
- O que é e quando usar 🚧
- Cliente MQTT 🚧
- Broker MQTT 🚧
- MQTT-SN 🚧
- Ponte REST 🚧
- Segurança 🚧
- Rede ruim 🚧
Cliente
Motores
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar