ATOUTFOX
COMMUNAUTÉ FRANCOPHONE DES PROFESSIONNELS FOXPRO
Visual FoxPro : le développement durable

Lecture d'un fichier XML volumineux par la méhode SAX   



L'auteur

Thierry
France France
Membre Simple
# 0000000016
enregistré le 13/10/2004

53 ans
PERRETIER Thierry
92800 PUTEAUX
Fiche personnelle


Note des membres
19,3/20
3 votes


Contributions > 20 - Trucs et Astuces

Lecture d'un fichier XML volumineux par la méhode SAX
# 0000000245
ajouté le 28/09/2005 15:05:03 et modifié le 08/11/2005
consulté 14471 fois
Niveau initié

Version(s) Foxpro :
VFP 9.0

Description

Lorsqu'un fichier XML est volumineux (plus de 1 Mo), sa lecture en utilisant XmlToCursor() est lente, voire impossible. Ceci est dû au fait que cette fonction utilise la technique XML-DOM (Document Object Model), c'est à dire que le fichier XML est chargé entièrement en mémoire sous forme d'objets hiérarchisés.

Voici un exemple en VFP utilisant la technique SAX  (Simple API for XML) via le composant MSXML.

Pour plus infos sur DOM et SAX, lire ceci : http://www.commentcamarche.net/xml/xmldomsax.php3

A noter que le .NET Framework fournit une 3ème méthode de lecture d'un XML :  XML Serializer XmlReader. C'est promis, dès que ce sera possible de l'utiliser facilement avec VFP (SEDNA ?), je posterai un exemple !

Code source :
#DEFINE FICHIERXML "c:\tmp\orders.xml"

CLEAR
CLOSE TABLES all
SET POINT TO "."

*--- création d'un gros fichier XML

WAIT WINDOW "Création fichier XML..." NOWAIT noclear

SELECT * ;
    FROM (_samples+"northwind\orders") ;
UNION ALL SELECT * ;
    FROM orders ;
UNION ALL SELECT * ;
    FROM orders ;
UNION ALL SELECT * ;
    FROM orders ;
INTO CURSOR xml

t1=Seconds()
ERASE FICHIERXML
CursorToXML("xml",FICHIERXML,1,512)
"CursorToXml"Seconds()-t1

*--- Lecture du fichier XML

CLOSE TABLES all
WAIT WINDOW "SAX..." NOWAIT noclear
t1=Seconds()

SELECT * ;
    FROM (_samples+"northwind\orders") ;
    WHERE .f. ;
    INTO CURSOR xml READWRITE

LOCAL o as Msxml.SAXXMLReader40
o=CreateObject("Msxml2.SAXXMLReader")
o.contentHandler = CreateObject("SAX","xml")
o.parseURL(FICHIERXML)
"SAX"Seconds()-t1
*-----

CLOSE TABLES all
WAIT WINDOW "XmlToCursor..." NOWAIT noclear

t1=Seconds()
XMLToCursor(FICHIERXML,"xml",512)
"XmlToCursor"Seconds()-t1
WAIT clear

****

DEFINE CLASS SAX AS SaxContentHandler

oEnreg = null
valeur=null
element =""
table=""

PROCEDURE init(tTable)
    this.table=m.tTable && nom de la table dans le XML
    SCATTER NAME this.oEnreg
ENDPROC

PROCEDURE IVBSAXContentHandler_endElement(strNamespaceURI AS STRING @, strLocalName AS STRING @, strQName AS STRING @) AS VOID
    IF m.StrLocalName == this.table
        INSERT INTO (Alias()) FROM NAME this.oEnreg
        SCATTER BLANK NAME this.oEnreg ADDITIVE

    ELSE
        WITH this.oEnreg
            cType = type("."+m.strLocalName)
            DO CASE
            CASE cType = "C"
                STORE this.valeur TO ("."+m.strLocalName)
            CASE InList(cType,"N","Y")
                STORE Val(this.valeur) TO ("."+m.strLocalName)
            CASE InList(cType,"D","T")
                STORE Evaluate("{^" + this.valeur + "}"TO ("."+m.strLocalName)

            * ... à complèter pour d'autres types de données

            ENDCASE
        ENDWITH
    ENDIF
ENDPROC

PROCEDURE IVBSAXContentHandler_characters(strChars AS STRING @) AS VOID
    this.valeur= StrChars
    IF this.valeur==""
        this.valeur=null
    ENDIF
ENDPROC

ENDDEFINE

***

DEFINE CLASS SaxContentHandler AS custom

IMPLEMENTS  IVBSAXContentHandler IN "MSXML2.DOMDocument"

PROCEDURE IVBSAXContentHandler_put_documentlocator(oDoc as Object)

ENDPROC

PROCEDURE IVBSAXContentHandler_documentLocator() AS VARIANT;
            HELPSTRING "Receive an object for locating the origin of SAX document events."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_startDocument() AS VOID;
            HELPSTRING "Receive notification of the beginning of a document."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_endDocument() AS VOID;
            HELPSTRING "Receive notification of the end of a document."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_startPrefixMapping(strPrefix AS STRING @, strURI AS STRING @) AS VOID;
            HELPSTRING "Begin the scope of a prefix-URI Namespace mapping."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_endPrefixMapping(strPrefix AS STRING @) AS VOID;
            HELPSTRING "End the scope of a prefix-URI mapping."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_startElement(strNamespaceURI AS STRING @, strLocalName AS STRING @, strQName AS STRING @, oAttributes AS VARIANT) AS VOID;
            HELPSTRING "Receive notification of the beginning of an element."
    * add user code here

ENDPROC

PROCEDURE IVBSAXContentHandler_endElement(strNamespaceURI AS STRING @, strLocalName AS STRING @, strQName AS STRING @) AS VOID;
            HELPSTRING "Receive notification of the end of an element."
    * add user code here

ENDPROC

PROCEDURE IVBSAXContentHandler_characters(strChars AS STRING @) AS VOID;
            HELPSTRING "Receive notification of character data."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_ignorableWhitespace(strChars AS STRING @) AS VOID;
            HELPSTRING "Receive notification of ignorable whitespace in element content."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_processingInstruction(strTarget AS STRING @, strData AS STRING @) AS VOID;
            HELPSTRING "Receive notification of a processing instruction."
    * add user code here
ENDPROC

PROCEDURE IVBSAXContentHandler_skippedEntity(strName AS STRING @) AS VOID;
            HELPSTRING "Receive notification of a skipped entity."
    * add user code here
ENDPROC

ENDDEFINE


Commentaires
le 28/09/2005, FredA a écrit :
Serializer... j'ai vu trainer quelque part la création d'un objet en VFP à partir d'une chaine csv ...
dès que je retrouve, je te dis ;)

le 28/09/2005, Thierry a écrit :
En fait, le remplacant de SAX dans .NET dont je voulais parler, c'est XmlReader.

http://msdn.microsoft.com/library/FRE/cpguide/html/cpconcomparingxmlreadertosaxreader.asp

XMLSerializer, c'est une évolution de XMLDOM (XML<->objets )

le 28/09/2005, Francis Faure a écrit :
c cool ton truc
le 29/09/2005, Thierry a écrit :
Pour le fun, voici un parser XML ultra rapide et 100% Fox :




PUBLIC ARRAY aTab(1)
ALines(aTab,FileToStr(FICHIERXML),1+4+16,">",Chr(9),Chr(13),Chr(10))
FOR EACH ligne IN aTab
i=At("</",m.ligne)
IF i > 0
attribut = Substr(m.ligne,i+2,Len(m.ligne)-i-2)
valeur = Left(m.ligne,i-1)
...
ENDIF
ENDFOR

le 18/02/2009, Olivier Hamou a écrit :
Bonsoir thierry,
Aurais tu plus d'infos sur ton parser 100% Fox ?
Est ce une solution aussi stable que Sax ?

Olivier,

le 18/02/2009, Thierry a écrit :
C'est seulement une solution très simpliste.

www.atoutfox.org - Site de la Communauté Francophone des Professionnels FoxPro - v3.4.0 - © 2004-2024.
Cette page est générée par un composant COM+ développé en Visual FoxPro 9.0-SP2-HF3