- Code: Select all Expand view RUN
- FUNCTION XMLToHash(cXMLFile)
LOCAL oXmlDoc, oRoot, hResult
TRY
oXmlDoc := TXmlDocument():New(cXMLFile)
CATCH
? "Error: No se puede leer el archivo XML: " + cXMLFile
RETURN NIL
END
oRoot := oXmlDoc:oRoot
hResult := hash()
IF oRoot:oChild == NIL
RETURN hResult
ENDIF
ProcessNode(oRoot:oChild, @hResult)
RETURN hResult
STATIC FUNCTION ProcessNode(oNode, hContainer)
LOCAL hNodeData
DO WHILE oNode != NIL
hNodeData := hash()
// Procesar el contenido del nodo
IF !Empty(oNode:cData)
hb_HSet(hNodeData, "value", oNode:cData)
ENDIF
// Procesar atributos si existen
IF !Empty(oNode:aAttributes)
hb_HSet(hNodeData, "attributes", hash())
HEval(oNode:aAttributes, {|k,v| hb_HSet(hNodeData["attributes"], k, v)})
ENDIF
// Procesar nodos hijos recursivamente
IF oNode:oChild != NIL
ProcessNode(oNode:oChild, @hNodeData)
ENDIF
// Agregar el nodo al contenedor
IF hb_HHasKey(hContainer, oNode:cName)
// Si ya existe una entrada para este nombre de nodo, convertir a array
IF !HB_ISARRAY(hContainer[oNode:cName])
hContainer[oNode:cName] := {hContainer[oNode:cName]}
ENDIF
AAdd(hContainer[oNode:cName], hNodeData)
ELSE
hb_HSet(hContainer, oNode:cName, hNodeData)
ENDIF
oNode := oNode:oNext
ENDDO
RETURN NIL
Esta funcion coloca:
["value"] para el contenido del nodo
["attributes"] para los atributos del nodo
En la prueba me funciono bien, utilizando el XML que coloco Rafa en su funcion:
- Code: Select all Expand view RUN
- FUNCTION TestXml2Hash()
Local pRoot, hHash, cXml
TEXT INTO cXml
<?xml version="1.0" encoding="utf-8"?>
<data>
<node1 nombre="cliente">Ejemplo XML</node1>
<node2>val2</node2>
<node3>val3</node3>
<group>
<node1>val4</node1>
<node2>val5</node2>
<node3>val6</node3>
</group>
<group>
<node1>val24</node1>
<node2>val25</node2>
<node3>val26</node3>
<extras>
<node1>Extra_val24</node1>
<node2>Extra_val25</node2>
<node3>Extra_val26</node3>
</extras>
</group>
<node7>val7</node7>
<node8>val8</node8>
</data>
ENDTEXT
hHash := XMLtoHash( cXml )
? hHash["data"]["node1"]["value"] // Muestra Ejemplo XML
? hHash["data"]["node1"]["attributes"]["nombre"] // Esto debería mostrar "cliente"
? hHash["data"]["node2"]["value"] // Muestra val2
// Para el primer grupo
? hHash["data"]["group"][1]["node2"]["value"] // Mostrará "val5"
// Para el segundo grupo
? hHash["data"]["group"][2]["node2"]["value"] // Mostrará "val25"
// Para acceder a extras del segundo grupo
? hHash["data"]["group"][2]["extras"]["node1"]["value"] // Mostrará "Extra_val24"
xBrowse(hHash)
RETURN nil
Si alguien puede probarla con un XML mas completo, me avisa si funcionó correctamente, o le pueden agregar algo mas de funcionalidad a esta función, lo puedan colocar en el foro.
Saludos
Carlos.