FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Obtener el Path en un Xml (SOLUCIONADO)
Posts: 230
Joined: Thu Sep 17, 2015 11:40 PM
Obtener el Path en un Xml (SOLUCIONADO)
Posted: Wed May 21, 2025 03:59 AM
Saludos una consulta sobre la lectura de un xml tengo trabajando esta función
Static Function XmlScan(hFile,cNodo,Clave,cValor)
local oXmlDoc  := TXmlDocument():New( hFile )
local oXmlIter := TXMLIterator():New( oXmlDoc:oRoot )
local oNodo,cdata,oTagActual
local mDbf:={}


DbCloseAll()
Aadd( mDbf,{"cPath" ,"C",250,0})
Aadd( mDbf,{"cName" ,"C",250,0})
Aadd( mDbf,{"cdata" ,"C", 50,0})
Aadd( mDbf,{"cKey"  ,"C", 50,0})
Aadd( mDbf,{"cvalue","C", 50,0})
Aadd( mDbf,{"Depth" ,"N", 2,0})

DbCreate( op:temp+"xmltodbf",mDbf )
NetUse( op:temp+"xmltodbf",.F.,"xml" )


While .T.
   oTagActual = oXmlIter:Next()
   If oTagActual != nil
      *MsgInfo( oTagActual:cName, oTagActual:cData )
      xml->(DbAppend())
      try
         xml->Depth := oTagActual:Depth()
         xml->cName := oTagActual:cName
         xml->cdata := oTagActual:cData
         HEval( oTagActual:aAttributes, { | cKey, cValue | (xml->cKey := cKey,xml->cvalue:= cvalue) } )
      catch o

      End
   Else
      Exit
   Endif

End

//FClose( hFile )
xbrowse("xml")

DbCloseAll()

Return cdata
pero necesito obtener el path completo de la linea, en el siguiente proceso lo conseguia con la funcion Path()

oXmlDoc := TXmlDocument():new( cFileXml )

IF oXmlDoc:nStatus = HBXML_STATUS_OK
   xmlnode := oXmlDoc:oRoot:oChild
   While xmlnode != NIL

      If xmlNode:Path() == cPath
         If pcount()=3
            cReturn := xmlnode:GetAttribute(atribute)
         Else
            cReturn := xmlNode:cData
         Endif
      Endif
      xmlNode := xmlNode:NextInTree()
   EndDo
EndIf
Gracias por el apoyo
Carlos Atuncar - CaSoftSystem
Chincha - Perú
+51983478218
carlosalbatun@gmail.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Obtener el Path en un Xml
Posted: Wed May 21, 2025 05:50 AM
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 230
Joined: Thu Sep 17, 2015 11:40 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Wed May 21, 2025 04:53 PM

Gracias Estimado Antonio por la pronta respuesta, quedo solucionado como necesitaba. Un abrazo

Carlos Atuncar - CaSoftSystem
Chincha - Perú
+51983478218
carlosalbatun@gmail.com
Posts: 1445
Joined: Mon Oct 10, 2005 02:38 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Wed May 21, 2025 06:06 PM
CARLOS ATUNCAR wrote: Gracias Estimado Antonio por la pronta respuesta, quedo solucionado como necesitaba. Un abrazo
Hola,

¿Es conocida a priori la estructura del XML que se va a recibir?

¿Cómo diferencias cada iteracion de un nodo iterativo ?
¿Y a su vez de otro nodo iterativo en otro nivel superior/inferior?

Saludos,
Carlos G.

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 230
Joined: Thu Sep 17, 2015 11:40 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Thu May 22, 2025 05:15 AM
Hola con estas funciones lo que hago es extraer todos los nodos que tienen datos a una dbf y con el cpath localizo los datos que necesito en este caso estoy creando un PDF desde el xml de una factura electronica y hasta el momento puedo sacar el información necesaria espero les sirva
Static Function XmlScan(hFile)
local oXmlDoc  := TXmlDocument():New( hFile )
local oXmlIter := TXMLIterator():New( oXmlDoc:oRoot )
local oTagActual,nId
local mDbf:={}
local cPath := ""
local lRet := .T.


Aadd( mDbf,{"id"    ,"N",  6,0})
Aadd( mDbf,{"cPath" ,"C",150,0})
Aadd( mDbf,{"cName" ,"C",100,0})
Aadd( mDbf,{"cdata" ,"C",150,0})
Aadd( mDbf,{"cKey"  ,"C", 50,0})
Aadd( mDbf,{"cvalue","C", 50,0})
Aadd( mDbf,{"Depth" ,"N", 2,0})

DbCloseAll()
DbCreate( op:temp+"xmltodbf",mDbf )
NetUse( op:temp+"xmltodbf",.F.,"xml" )
Index On xml->cPath TAG cPath
Set Orde To 1

nId := 1
While .T.
   oTagActual = oXmlIter:Next()
   If oTagActual != nil
      xml->(DbAppend())
      xml->id := nId
      try
         cPath := BuildPath(oTagActual)
         xml->cpath := cPath
         xml->Depth := oTagActual:Depth()
         xml->cName := oTagActual:cName
         xml->cdata := oTagActual:cData
         HEval( oTagActual:aAttributes, { | cKey, cValue | (xml->cKey := cKey,xml->cvalue:= cvalue) } )
      catch o

      End
      nId++
   Else
      Exit
   Endif

End

If xml->(Lastrec())=0
   lRet := .F.
Endif

Return lRet


* Función auxiliar para construir el path completo
Static Function BuildPath(oNode)
   local cPath := ""
   local oCurrent := oNode
   local aPath := {}

   * Recorrer los nodos padres hasta la raíz
   while oCurrent != nil
      if !Empty(oCurrent:cName)
         AAdd(aPath, oCurrent:cName)
      endif
      oCurrent := oCurrent:oParent
   end

   * Construir el path en orden inverso, uniendo con "/"
   for n := Len(aPath) to 1 step -1
      cPath += "/" + aPath[n]
   next

   * Eliminar la barra inicial si es necesario
   if Left(cPath, 1) == "/"
      cPath := SubStr(cPath, 2)
   endif

return cPath

Static Function ExtraerXml(xPath)
local cdata := ""

xml->(DbSeek(xPath))
If xml->(Found())
   cdata := Alltrim(xml->cdata)
   If Len(cdata)=0
      cdata := .T.
   Endif
Endif

Return cdata
Carlos Atuncar - CaSoftSystem
Chincha - Perú
+51983478218
carlosalbatun@gmail.com
Posts: 1445
Joined: Mon Oct 10, 2005 02:38 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Thu May 22, 2025 07:20 AM

Creo que entiendo como trabajan estas funciones.

Pero si tengo:

<Datos>

<Persona>

<Nombre>Juan<\Nombre>

<TelefonoS>

<Telefono>123456789<\Telefono>

<Telefono>234567891<\Telefono>

<\TelefonoS>

<\Persona>

<Persona>

<Nombre>Pedro<\Nombre>

<TelefonoS>

<Telefono>234567891<\Telefono>

<\TelefonoS>

<\Persona>

<Persona>

<Nombre>Ana<\Nombre>

<TelefonoS>

<Telefono>345678912<\Telefono>

<\TelefonoS>

<\Persona>

<\Datos>

¿Cómo extraerías los teléfonos de cada Persona?

Muchas gracias,

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 230
Joined: Thu Sep 17, 2015 11:40 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Fri May 23, 2025 05:19 AM

cuando son varios datos con nodos similares lo que puedes hacer es filtrar por el campo cpath y sacar la información necesaria

Carlos Atuncar - CaSoftSystem
Chincha - Perú
+51983478218
carlosalbatun@gmail.com
Posts: 1445
Joined: Mon Oct 10, 2005 02:38 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Fri May 23, 2025 08:17 AM
CARLOS ATUNCAR wrote: cuando son varios datos con nodos similares lo que puedes hacer es filtrar por el campo cpath y sacar la información necesaria
Si, ¿Pero como sabes si el teléfono 234567891 pertenece a Juan o a Pedro?
O que el 345678912 es de Anna?
Entiendo que el path será el mismo para los 3.

Gracias,

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 230
Joined: Thu Sep 17, 2015 11:40 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Fri May 23, 2025 03:53 PM
FiveWiDi wrote: Creo que entiendo como trabajan estas funciones.

Pero si tengo:

<Datos>
<Persona>
<Nombre>Juan<\Nombre>
<TelefonoS>
<Telefono>123456789<\Telefono>
<Telefono>234567891<\Telefono>
<\TelefonoS>
<\Persona>
<Persona>
<Nombre>Pedro<\Nombre>
<TelefonoS>
<Telefono>234567891<\Telefono>
<\TelefonoS>
<\Persona>
<Persona>
<Nombre>Ana<\Nombre>
<TelefonoS>
<Telefono>345678912<\Telefono>
<\TelefonoS>
<\Persona>
<\Datos>

¿Cómo extraerías los teléfonos de cada Persona?

Muchas gracias,
tomando tu ejemplo podria hacer una ubicacion por el path nombre que me debe salir persona/nombre y como lo tengo indexado por la columna cpath y tengo una columna id tomaria los id para saber donde comienza cada persona y haria un filtro dentro de ese rango y ubicaria el cpath de cada telefono
Carlos Atuncar - CaSoftSystem
Chincha - Perú
+51983478218
carlosalbatun@gmail.com
Posts: 230
Joined: Thu Sep 17, 2015 11:40 PM
Re: Obtener el Path en un Xml (SOLUCIONADO)
Posted: Fri May 23, 2025 03:56 PM
este ejemplo es las lineas de una factura que contienen las mismas caracteristicas y en una factura pueden ser una linea o muchas y lo he resuelto de esta forma espero me deje entender
Static Procedure Items
local mLineas:= {}
local coun,a

xml->(DbSeek("Invoice/cac:InvoiceLine"))

If xml->(Found())
   While !xml->(Eof()) .AND. Alltrim(xml->cpath) == "Invoice/cac:InvoiceLine"
      coun := Len( mLineas )+1
      Asize( mLineas,coun )
      mLineas[coun] := xml->id
      xml->(DbSkip())
   EndDo
Endif

For a:= 1  TO Len( mLineas )
   x1 := mlineas[a]
   If a+1>Len( mLineas)
      x2 := xml->(Lastrec())
   Else
       x2 := mlineas[a+1]
   EndIf
   Select("xml")
   Set Filter To xml->Id>=x1 .AND. xml->id <=x2
   xml->(DbGoTop())
   xbrowse("xml","Rangos"+Alltrim(Str(x1))+" Al "+Alltrim(Str(x2)) )

   tmp2->(DbAppend())
   tmp2->prod_nom := ExtraerXml("Invoice/cac:InvoiceLine/cac:Item/cbc:Description")
   tmp2->prod_can := Val(ExtraerXml("Invoice/cac:InvoiceLine/cbc:InvoicedQuantity"))
   tmp2->prod_pre := Val(ExtraerXml("Invoice/cac:InvoiceLine/cac:Price/cbc:PriceAmount"))
   tmp2->prod_bas := Val(ExtraerXml("Invoice/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount"))
   tmp2->prod_igv := Val(ExtraerXml("Invoice/cac:InvoiceLine/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount"))
   tmp2->prod_tot := tmp2->prod_bas+tmp2->prod_igv
Next

Return
Carlos Atuncar - CaSoftSystem
Chincha - Perú
+51983478218
carlosalbatun@gmail.com

Continue the discussion