Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VFP 6 help read xml

Status
Not open for further replies.
Mar 13, 2017
8
PH
Good day!

just wanna ask if i can: >>>>>>>USING ONLY FOXPRO 6.0<<<<<

only read between <bol_reference>
<Bol_reference>EGLV020700045087</Bol_reference>

like EGLV020700045087 -had 16 characters

and another
<Bol_reference>COAU7010692680</Bol_reference>

like COAU7010692680 -had 13 characters

using alltrim(substr(x,15,13) will read also <\bol

please help just read only between

thanks
 
additional info >>>USING VFP6.0<<<<<<<<<<

iam already create the program using vfp6 only
its like xml to dbf program..

thanks again..
 
Rick Strahl has offered his wwXML library before VFP had XML functions. I'm not sure the latest version still works in VFP6, but it's worth a try. What I know is, it works with MSXML3, so the XML functionality does not require VFP7+ functions for the core XML handling. But there might be usage of any more convenient VFP7,8,9 functionality surrounding the MSXML3 usage for XML parsing and creation. If you get OLE errors with it, try to install MSXML3 latest version from here and see here for upgrade up to post sp11 msxml3.dll


That would solve more than just your detail problem.

And by the way, if wwXML fails, you might use MSXML yourself, the download I point to also is an SDK, a development kit.

Bye, Olaf.
 
berniebogs said:
only read between <bol_reference>
<Bol_reference>EGLV020700045087</Bol_reference>
like EGLV020700045087 -had 16 characters
and another
<Bol_reference>COAU7010692680</Bol_reference>
like COAU7010692680 -had 13 characters

Since XML files are nothing more than Text files AND since you only want a portion of the XML data, you can always write your own routine to pretty easily read the information out of the files.

Code:
cFileString = FILETOSTR(<XML File>)
* --- Then process the string to extract what you need ---
cStartTag = "<Bol_reference>"
cEndTag = "</Bol_reference>"
DO WHILE .T.
   nTag1 = AT(cStartTag,cFileString)
   if nTag1 > 0
      nTag2 = AT(cEndTag,cFileString)
      * --- Now, knowing where both TAG's are, get the data in between the Tags ---
        cXMLData = SUBSTR(cFileString,(nTag1 + LEN(cStartTag)),(nTag2-nTag1)-LEN(cStartTag))

      * --- Do whatever you want to do with the data ---
        <do whatever>

      * --- Now reduce cFileString to remove the first Set of data ---
       cFileString = SUBSTR(cFileString, nTag2 + LEN(cEndTag))   && nTag2 + LEN(cEndTag)
   ELSE
      EXIT
   ENDIF
ENDDO

Good Luck,
JRB-Bldr

 
Since XML files are nothing more than Text files AND since you only want a portion of the XML data, you can always write your own routine to pretty easily read the information out of the files.

I agree. And here's another way of doing it:

Code:
cFileString = FILETOSTR(<XML File>)
* --- Then process the string to extract what you need ---

lnCount = 1
lcExtract = ""
DO WHILE .T.
  lcExtract = STREXTRACT(cFileString, "<Bol_reference>", "</Bol_reference>", lnCount)
  IF EMPTY(lcExtract)
    EXIT
  ENDIF
  * do whatever you want to do to the data between the tags
  <do whatever>
  lnCount = lnCount + 1
ENDDO

I'm not saying this is necessarily better than JRB's suggestion - just an alternative approach (and possibly a bit more concise).


[highlight #EDD400]EDIT:[/highlight] [highlight #EDD400][/highlight]Not sure if STREXTRACT() was available in VFP 6.0. Never mind. I'll leave this code in place in case it is of interest to anyone else.

Mike
__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike - that's a good and more concise approach. Thanks for posting it.

However in the book: Build Your Own Framework with Visual FoxPro it says that StrExtract() was introduced in Viaual FoxPro 7.0

berniebogs - Good Luck
JRB-Bldr
 
Though I began with Foxpro in VFP6 I also don't know exactly what functions were (are) in there and which not. Anyway, you can automate COM classes and I'd opt to use an XMLDocument Object to read in XML and then parse that out:

Code:
o = CreateObject("Microsoft.XMLDOM")
o.loadXML("<rows><Bol_reference>EGLV020700045087</Bol_reference><Bol_reference>COAU7010692680</Bol_reference></rows>")
oNodes = o.selectNodes("//Bol_reference")
FOR EACH oNode IN oNodes
   ? oNode.text
ENDFOR

Not sure you can do FOR EACH, but you could also do
Code:
o = CreateObject("Microsoft.XMLDOM")
o.loadXML("<rows><Bol_reference>EGLV020700045087</Bol_reference><Bol_reference>COAU7010692680</Bol_reference></rows>")
oNodes = o.selectNodes("//Bol_reference")
FOR lnCount = 0 TO oNodes.length-1
   ? oNodes.item(lnCount).text
ENDFOR
About this version I'm pretty sure, COM inteop and CREATEOBJECT are older, and besides variables and FOR...ENDFOR loop also surely existing very long, the rest of the code uses the methods of the Microsoft.XMLDOM object, which only depends on it and not VFP.

Bye, Olaf.
 
thanks for all your suggestions.. i will try it all on monday at office..
 
Olaf said:
Though I began with Foxpro in VFP6 I also don't know exactly what functions were (are) in there and which not.

There is a whole series of "concordances" on the Fox Wiki that will tell you which functions and commands were introduced in each version:


Also for properties, events, methods, data types, base classes, and more - even code pages.

If you have old versions of HackFox, those are also a good way to keep track of what came in each version.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, yes. My approach would always be to look at the differnt help topic versions, but that only goes back to VFP7 in the MSDN library online.

What I did even way back then in VFP6 is create an internationalization routine, which looked through all source code for string literals besides captions and other UI text, for putting all these strings into a table for translation. Of course not those literals, which are technical, but aside of that translation specific behaviour this was some kind of STREXTRACT with start- and end delimiters of strings. I did quite the same thing as JRB-BLDR suggested, looking for a delimiter with AT, then apply SUBSTR to get the rest of the string after the delimiter and looking for the end delimiter in that. The part up to the second delimiter then of course is the string literal.

I still have that code in use, though it could nowadays also be done with STREXTRACT, my code has some specialties in leaving out comments, looking for llinefeed and some more things o avoid quirks in string detection you can easyly have - just thinlk of mentioning a 17" monitor in a comment, for example. All of these exception rules are even not necessary with XML having no such things to avoid in your extraction.

Today I would always go about XML or HTML parsing with STREXTRACT, it is very fine for exactly that purpose, unfortunately not available. Defining a STREXTRACT function using AT would be a good option to later simply use the native function, when converting to VFP9, for example, though the route may be to stay in VFP6 and reimplement in JAVA or .NET or some other current development stack, rather than convert to VFP9.

Bye, Olaf.
 
If you have old versions of HackFox, those are also a good way to keep track of what came in each version.

And, in fact, if you have HackFox 7, you can right-click in the contents pane and choose Customize, then choose Custom to limit the list to commands introduced in particular versions.

Tamar
 
Here's a STREXTRACT for VFP6, you might use for the simple cases you need.

Code:
#if VERSION(4)<"07"
   #Define StrExtract StrExtractV6
#Endif   

? 'test1:'+STREXTRACT("AAAABZ","A","Z",1)
? 'test2:'+STREXTRACT("AAAABZ","A","Z",2)
? 'test3:'+STREXTRACT("AAAABZ","A","Z",3)
? 'test4:'+STREXTRACT("AAAABZ","A","Z",4)
? 'test5:'+STREXTRACT("AAAABZ","A","Z",5)
? 'test6:'+STREXTRACT("AAAABZ","1","2")
? 'test7:'+STREXTRACT("A1AA2Z","1","2")

FUNCTION StrExtractV6(cSearchexpression, cBeginDelim, cEndDelim, nOccurrence)
   * Not emulating nFlags parameter
   ?? "emulated STREXTRACT:"
   nOccurrence = IIF(EMPTY(nOccurrence),1,nOccurrence)
   LOCAL lnBegin, lcRest
   lnBegin = AT(cBeginDelim, cSearchexpression, nOccurrence)
   IF lnBegin=0
      RETURN '' && begin delimiter not found
   ENDIF
   lcRest = SUBSTR(cSearchexpression,lnBegin+1)
   RETURN LEFT(lcRest,MAX(0,AT(cEndDelim,lcRest)-1))
ENDFUNC

I can compare the results of STREXTERACT (native since VFP7) and STREXTRACTV6 for you and others may confirm it's working as intended:
[pre]test1:emulated STREXTRACT:AAAB
test2:emulated STREXTRACT:AAB
test3:emulated STREXTRACT:AB
test4:emulated STREXTRACT:B
test5:emulated STREXTRACT:
test6:emulated STREXTRACT:
test7:emulated STREXTRACT:AA

vs normal STREXTRACT:

test1:AAAB
test2:AAB
test3:AB
test4:B
test5:
test6:
test7:AA
[/pre]

Sample usage in Mikes example code:
Code:
#if VERSION(4)<"07"
   #Define STREXTRACT STREXTRACTV6
#Endif  

cFileString = FILETOSTR(GetFile('xml'))
* --- Then process the string to extract what you need ---

lnCount = 1
lcExtract = ""
DO WHILE .T.
  lcExtract = STREXTRACT(cFileString, "<Bol_reference>", "</Bol_reference>", lnCount)
  IF EMPTY(lcExtract)
    EXIT
  ENDIF
  ? lcExtract && do whatever you want to do to the extract from between the tags 
  lnCount = lnCount + 1
ENDDO

FUNCTION STREXTRACTV6(cSearchExpression, cBeginDelim, cEndDelim, nOccurrence)
   * Not emulating nFlags parameter
   nOccurrence = IIF(EMPTY(nOccurrence),1,nOccurrence)
   LOCAL lnBegin, lcRest
   lnBegin = AT(cBeginDelim, cSearchExpression, nOccurrence)
   IF lnBegin=0
      RETURN '' && begin delimiter not found
   ENDIF
   lcRest = SUBSTR(cSearchexpression,lnBegin+LEN(cBeginDelim))
   RETURN LEFT(lcRest,MAX(0,AT(cEndDelim,lcRest)-1))
ENDFUNC

It doesn't only look as more code, it is more code. But having that function in a PRG you SET PROCEDURE to in main.prg - or within main.prg - and always having the preprocessor directives in your VFP6 code using the STREXTRACT calls, you A) can make use of the STREXTRACT function in VFP6, and B) will not need to change anything when compiling in VFP7 or later and will use the faster native STREXTRACT function.

That's what you can call upward compatibility, having emulated a functionality of a later VFP version in an earlier VFP version to simplify code and use it before it's available as native function. I made it a little simpler in not emulating the optional nFlags parameter, but you also don't need it.

Bye, Olaf.
 
For another approach, I wondered about using GETWORDCOUNT()and GETWORDNUM(). Those functions aren't available in VFP 6.0 either, but there is an equivalent Foxtools function: WordNum().

Something like should work:

Code:
SET LIBRARY TO (HOME() + "Foxtools")

cFileString = FILETOSTR(<XML File>)
* --- Then process the string to extract what you need ---
cStartTag = "<Bol_reference>"
cEndTag = "</Bol_reference>"

cFileString = STRTRAN(cFileString, cStartTag, "#")
cFileString = STRTRAN(cFileString, cEndTag, "#")

lnI = 2
DO WHILE .T.
  lcExtract = WordNum(cFileString, lnI, "#")
  IF EMPTY(lcExtract)
    EXIT
  ENDIF
	 
  * do whatever you want to do to the data between the tags
  <do whatever>
	
  lnI = lnI + 2
ENDDO

A problem with WordNum() is that the start and end delimiters must be the same character. You can't use "<Bol_reference>" as the start delimiter and "</Bol_reference>" as the end delimiter. So I am changing each of those strings to a single character: "#". (Of course, this assumes that "#" does not appear anywhere else in the input file. If it does, you must choose a different character.)

The reason that the loop starts with the second occurrence of the word (lnI = 2), and then looks at every second occurrence after that (lnI = lnI + 2), can be seen by looking at the following example:

Code:
<start of file>
  <Bol_reference>1234</Bol_reference>
  <Some other tag>ABCD</Some other tag>
   <Bol_reference>5678</Bol_reference>
<end of file>

After substituting the #s, we get this:

Code:
<start of file>
  #1234#
  <Some other tag>ABCD</Some other tag>
   #5678#
<end of file>

So, if we extracted every word, we would get everything up to the first # (which we don't want), then everything between the first and second (which we do want), then between the second and third (don't want), then between the third and fourth (do want), and so on. That's why we are skipping the first, third, etc. occurrences.

I admit this code is not particularly bullet-proof (it makes some assumptions about the contents of the input file), but at least it demonstrates what else is possible - and if nothing else it's a reason to remember about Foxtools if you are using an older version of VFP.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top