Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Registros de Facturacion y Eventos (XML) (https://www.clubdelphi.com/foros/forumdisplay.php?f=67)
-   -   Leer nodo de un xml (https://www.clubdelphi.com/foros/showthread.php?t=97286)

GustavoCruz 14-03-2025 23:23:06

Leer nodo de un xml
 
1 Archivos Adjunto(s)
Hola amigos del foro, realmente no sabía dónde ubicar la pregunta.

Tengo el xml de una factura electrónica y necesito poder leer y modificar un dato.
<AdditionalInformation>
<Name>CODIGO_PRESTADOR</Name>
<Value>1</Value>
</AdditionalInformation>

del xml modificar <Value>1</Value> siempre y cuando encuentre <Name>CODIGO_PRESTADOR</Name>

Adjunto les dejo el archivo.

Les agradezco toda la ayuda que me puedan brindar

Gracias

Neftali [Germán.Estévez] 17-03-2025 09:17:55

En los foros puedes encontrar mucha información al respecto.
Busca sobre la clase TXMLDocument.

En la case TXMLDocument, tienes métodos de LoadFromFile y SaveToFile.

Puedes cargar el fichero XML. Navegar por los nodos (ChildNodes,...) modificar los valores y volverlo a guardar.

Revisa estos hilos, aunque si buscas encontrarás más:
https://www.clubdelphi.com/foros/showthread.php?t=37223
https://www.clubdelphi.com/foros/showthread.php?t=89834
https://www.clubdelphi.com/foros/showthread.php?t=96144

Osorio 17-03-2025 22:02:59

Recientemente hice esta función que recorre un XML y obtengo el valor que tiene en los nodos que tienen un nombre especifico. Puede ser un punto de partida.

Código Delphi [-]

function TDataModulo.XMLExtraerNodo(const XMLPar: widestring; const PNodo: String): TStringList;
var
      XMLDoc: IXMLDocument;
      Lista: TStringList;
      procedure AddNodes(ParentNode: TTreeNode; XMLNode: IXMLNode);
      var
        ChildNode: IXMLNode;
        TreeNode: TTreeNode;
      begin
        if (XMLNode.IsTextElement) then
          if XMLNode.NodeName = PNodo then
              Lista.Add(XMLNode.Text);
        ChildNode := XMLNode.ChildNodes.First;
        while ChildNode <> nil do
        begin
          AddNodes(TreeNode, ChildNode);
          ChildNode := ChildNode.NextSibling;
        end;
      end;
begin
  try
    lista:= TStringList.Create;
    Lista.Clear;
    XMLDoc := LoadXMLData(XMLPar);
    if Assigned(XMLDoc.DocumentElement) then
      AddNodes(nil, XMLDoc.DocumentElement);
  finally
    Result:= lista;
  end;
end;



Teniendo en cuenta que el XML es un texto (String) tambien se pueden hacer reemplazos de texto usando comodines.


Código Delphi [-]
    
MyXML := StringReplace(MyXML,'#COMODINUSUARIO',WideString(XMLUser), [rfReplaceAll, rfIgnoreCase]);

Saludos,

GustavoCruz 19-03-2025 14:00:00

Hola buenos días desde Colombia, gracias por sus respuestas. efectivamente he visto ejemplos sobre TXMLDocument. que funcionan perfectamente en otros XML, pero para el caso específico del esquema de la factura que les adjunté no funcionan; por ello lo envié

Gracias por el tiempo dedicado

Neftali [Germán.Estévez] 19-03-2025 16:35:59

No me había dado cuenta de que el nodo que has puesto al inicio no está dentro del XML directamente.

Código:

<AdditionalInformation>
  <Name>CODIGO_PRESTADOR</Name>
  <Value>1</Value>
</AdditionalInformation>

En realidad esa parte que has puesto, está dentro de un bloque del XML marcado con CDATA.
Código:

...
<cbc:Description><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
                                          <Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:...
...
<Name>CODIGO_PRESTADOR</Name>
...
...

Es decir, tienes un XML general, con un nodo <cbc::Description> que dentro tiene un elemento CDATA, y que ese elemento CDATA es otro XML.
El problema es que un elemento CDATA, según su definición:

"En XML, una sección CDATA (Character Data) es utilizada para incluir contenido que contiene caracteres especiales sin que se interpreten como marcado XML por el analizador. "

Es decir, que el analizador, de por si, no va a evaluar ese XML que está dentro del CDATA.
Seguramente (no lo he probado), cuando llegues al elemento CDATA, deberás coger ese texto, crear un nuevo TXMLDocument, meter el texto dentro y "parsearlo" de nuevo.
Y ahora sí, si "parseas" ese segundo XML sí te encontrará el elemento: <Name>CODIGO_PRESTADOR</Name>

Neftali [Germán.Estévez] 19-03-2025 16:37:07

No me había dado cuenta de que el nodo que has puesto al inicio no está dentro del XML directamente.

Código:

<AdditionalInformation>
  <Name>CODIGO_PRESTADOR</Name>
  <Value>1</Value>
</AdditionalInformation>

En realidad esa parte que has puesto, está dentro de un bloque del XML marcado con CDATA.
Código:

...
<cbc:Description><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
                                          <Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:
...

Es decir, tienes un XML general, con un nodo <cbc_dospuntos_Description> que dentro tiene un elemento CDATA, y que ese elemento CDATA es otro XML.
El problema es que un elemento CDATA, según su definición:

"En XML, una sección CDATA (Character Data) es utilizada para incluir contenido que contiene caracteres especiales sin que se interpreten como marcado XML por el analizador. "

Es decir, que el analizador, de por si, no va a evaluar ese XML que está dentro del CDATA.
Seguramente (no lo he probado), cuando llegues al elemento CDATA, deberás coger ese texto, crear un nuevo TXMLDocument, meter el texto dentro y "parsearlo" de nuevo.
Y ahora sí, si "parseas" ese segundo XML sí te encontrará el elemento: <Name>CODIGO_PRESTADOR</Name>


La franja horaria es GMT +2. Ahora son las 21:36:49.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi