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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

FILETOSTR error while converting XML 1

Status
Not open for further replies.

peteschulte

IS-IT--Management
Nov 21, 2008
41
US
Hello Coders,
In debugging the following code, I referred to the Help files, shortened the file name, inspected the file itself -- I'm stuck!
See attachment
Stepping into this line, I got "File does not not exist" -- xmlcontent = FILETOSTR(xmlfile)
Code:
SET DEFAULT TO C:\tempVFP\12-26_reStart
Local lcXML, loXMLAdapter, loXMLTable
Close Tables All

SET STEP ON 

xmlfile="C0_5528.xml"
xmlcontent = FILETOSTR(xmlfile)
lcXML = xmlcontent 

loXMLAdapter = CreateObject("XMLAdapter")

loXMLAdapter.LoadXML(lcXML,.F.,.T.)
&& 	XMLAdapter.LoadXML( cXMLDocument [, lFile [, lValidateOnParse ]] )

&&	For Each loXMLTable in loXMLAdapter.Tables
   loXMLTable.ToCursor(lcXML)
  	COPY TO (loXMLTable.Alias+".dbf")
&&	ENDFOR

SET
Thank you for your help and Happy Coding in 2009!
 
Stepping through from the top:
it is setting the default directory.
It is not seeing the file. When I used fopen(C0_5528.xml) -- trying it without the quotation marks -- I got error message "Alias not found
 
Also checked permissions on the file and the folder.
When I changed the file extension to .txt the program found the file and gave me an xml parse error. UTF-8 incompatible with VFP8?
Thanks for your ideas and/or solution!
 
try
xmlfile=["C0_5528.xml"]

This old world keeps spinning round - It's a wonder tall trees ain't layin' down
 
Any other suggestions?

Hello white605,
I like your tag about the trees!
Thanks for the suggestion, which did not work.
I'm back at my office on a different computer than at home where I posted this thread.
This pretty much removes any questions about the machine's being defective.
Attached is a pic of your suggestion with results.

Thanks,
Pete
 
 http://web.afts.com/peter/useSquareBrackets.jpg
Hi Peteschulte,

Sorry if this is stating the obvious, but ... if your FILETOSTR() is reporting that the file doesn't exist, the first thing to check is whether the file does indeed exist. And whether it is either in the default directory or on the search path.

I'd focus on that for now, and forget about the XML stuff and the parse error.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
GOOD ADVICE, already considered
You are right Mike!

...and I have been doing that. Making sure that it is in the folder, opening it in Dreamweaver, etc.

This morning when I changed the extension to .txt and inserted "? xmlcontent" into the code,
I was able to see the xml contents of the file on the VFP console.

Thank you for sound advice,
Peter


ANY OTHER GOOD ADVICE IS WELCOME!!
 
I can't see why this is working now and did not work before. Look at the jpeg and you'll see the file contents dumped onto the console. Hooray!


Code:
SET DEFAULT TO C:\temp-CallDetail\12-29
&&	Local lcXML, loXMLAdapter, loXMLTable
Close Tables All

currentDir = SYS(5) + CURDIR()
? currentDir + CHR(13)+CHR(10)

SET STEP ON

xmlfile=("C0_5528.xml")
? xmlfile + CHR(13)+CHR(10)

xmlcontent = FILETOSTR(xmlfile)

? xmlcontent + CHR(13)+CHR(10)

It may be something hidden about the file I copied, then renamed as .txt then back to .xml. This file was the result of "Free Trial" software. When I want to rename fields in the associated table, I can't change the Read Only attribute by using Set Exclusive On, File Properties, etc. The lesson being to create a new file and paste into it if in doubt about the original.

Now if the MVP's wish to close the thread. That's fine. Otherwise, I'll check later for any discussion, then close it myself.
Thanks,
Pete
 
 http://web.afts.com/peter/readXMLfileOkay.jpg
Hi Pete,

see the difference:

First you did:
Code:
SET DEFAULT TO C:\tempVFP\12-26_reStart

Now as it works you did:
Code:
SET DEFAULT TO C:\temp-CallDetail\12-29

Maybe you also copied the xml file around to the other directory, but anyway, if vfp does not find the file it's surely no vfp bug, that would be known. If the file exists there vfp either has no access to the whole directory or one of it's parent dirs or the file is hidden or in a hidden dir, there is no other way.

Another issue you could have had, is that you set up Windows Explorer to suppress file extensions of known extensions and then added a txt or xml, so the real filename may have been C0_5528.xml.txt or C0_5528.txt.xml during your experiments.

I turn that option off as the default, because as a programmer it's important you know the file names as they are for real, for a user it may be sufficient to see the main part of the filename, the stem, together with the icon associated with eg the ms word doc ending or something else, but for the programmer this is of no value.

I don't think it was an access right issue, then you would have got another error.

Did you really SET DEFAULT TO ... the way you posted or did you simplify the code where you predetermine the path like C:\temp-CallDetail\12-29 with eg a date, 12-29 looks like a date part. If you do that wrongly CD will not put you in the right path you thought of.

Anyway I'd advice you do the following steps regarding paths and files:

First of all don't hardcode paths into code, make them part of a configuration, eg a free dbf. You may want to change you directories organisation at some point and then you're either stuck with such code and forced to leave the files where they are or you need to find all paths in the code an change them accordingly.

Make some paths.dbf with the fields cPathalias and cPath. The pathalias could be a short description of the path you take to lookup the real path, in your example that pathalias may be XMLFILES. cPath could be a Memo and cPathalias a C(20) field.

You will have paths that are specific to one app or to all apps and so you'd ideally have one local paths.dbf, local to your app, and some public paths.dbf somewhere in a network share. Then put the path to the public paths dbf into the local paths dbf and you only need to know that path. And that path could be Justpath(Sys(16,0)), which is "here", the path where the main.prg is located.

If you have that you'd do something like this:

Code:
Local lcXMLPath
lcXMLPath = GetPath("XMLFILES")

Local lcXMLFile, lcXML
lcXMLFile = AddBS(lcXMLPath)+"C0_5528.xml"

lcXML = FileToStr(lcXMLFile)
...

Function GetPath()
   Lparameters tcPathalias, tlGlobal

   Local lcPathsAlias
   lcPathsAlias = iif(tlGlobal,"global","local")+"paths"

   Local lcPath
   If !Used(lcPathsAlias)
      If tlGlobal
         * get global path from local paths (tlGlobal = .F. explicitly)
         Use (GetPath("GLOBALPATHS",.F.) In 0 Alias (lcPathsAlias)
      Else
         Use (Justpath(Sys(16,0))+"paths.dbf") In 0 alias (lcPathsAlias)
      Endif
   Endif
   Select cPath From (lcPathsAlias);
   Where cPathalias=tcPathalias;
   Into Cursor curPath
   If _tally = 1
      lcPath = curPath.cPath
   Else
      Messagebox("Path "+tcPathalias+" not found! Please add it to the appropriate paths.dbf")
      Suspend
   Endif

   Return lcPath 
Endfunction

You may implement GetPath() differently, the point is, that it will be the only function needing a "static" path, and even that is determined dynamically with SYS(16,0). You need at minimum the two paths dbfs and the path to the GLOBALPATHS within the local paths.dbf for this function to work properly.

You then get local paths by GetPath(cPathalias) and global ones by GetPath(cPathalias,.T.).

As a side effect you will never need to CD or SET DEFAULT TO some path, as you always can put together a full path easily. But even if you do, then CD (GetPath(cPathalias)) will work anyway. All commands having paths as their options should be used with a name expression, eg CD ("some path") or also CD (FunctionResultingInSomePath()) Otherwise CD some path will look for "some" and error on "path" as that is parsed as an additional and invalid option, not as part of the path. CD lcSomevariablename will look for a path called lcSomevariablename and not look for the path stored in lcSomevariablename, therefore you also need CD (lcSomevariablename) in that case.

The rule regarding paths and filenames and name expressions all in all is very easy: Always use name expressions (...) when you use a command, never make use of the option to directly write paths. So een use CD ("c:\temp") instead of CD c:\temp, and you'll never need to think about when you need to change because of spaces within a path.

A Function like FileToStr() will not take a directly written path anyway, but evaluate the value of it's path parameter, therefor you don't need name expressions there, but can use them anyway.

And another recommendation: ADIR() will always look on disk for the file, while most functions will also search along paths set by SET PATH. So you can check if VFP finds a sepcific file by IF ADIR(aDummy,<<specific file name>>)=1. If ADIR gives 1 then it there for sure. Otherwise i may be existing but hidden or vfp has no access to some dir on the way to the file.

Bye, Olaf.
 
Hi again,

could it simply be an issue of the date? You used C:\tempVFP\12-26_reStart, which somehow includes 26th of december, and C:\temp-CallDetail\12-29, which includes 29th december. So maybe the program generating the xml file will put it into varying directories including the date in the form MM-DD. Then you need code to dynamically generate that directory name and import from there and not from a static directory.

Bye, Olaf.
 
Hello Olaf,
A quick clarification before I read on into your post. The folder name was different, as I noted in my reply to Mike:

"I'm back at my office on a different computer than at home where I posted this thread.
This pretty much removes any questions about the machine's being defective."

 
Hi again, Olaf,
This is where we agree on the probable cause.
Code:
Another issue you could have had, is that you set up Windows Explorer to suppress file extensions of known extensions and then added a txt or xml, so the real filename may have been C0_5528.xml.txt or C0_5528.txt.xml during your experiments.

I turn that option off as the default, because as a programmer it's important you know the file names as they are for real, for a user it may be sufficient to see the main part of the filename, the stem, together with the icon associated with eg the ms word doc ending or something else, but for the programmer this is of no value.

Thank you for the specific solution, where I was just intuiting the problem: toggle Windows Explorer NOT to suppress file extensions.
I checked every access permission I could think of.
And thanks very much for the gloss on using paths in code, really top-notch!
Now that the text is available from the XML file, I may have cause for a new thread for the parse error, we'll see. (It's throwing an error on a space between words. Where I removed a crlf, it no longer throws an error.)
Thanks again!
Peter
 
Next time, do a filetostr(getfile()) and check the results
 
Hi Olaf,
I'm working with the path db's local and global as you advised. Here is the code.

Code:
&& creates 14 tables and requires 10 minutes

&& SET DEFAULT TO \\Gmc\d\Stmt\Monterey\UB_Test_1231\


***********************
Local lcXMLPath
lcXMLPath = GetPath("XMLFILE")

Local lcXMLFile, lcXML
lcXMLFile = AddBS(lcXMLPath)+"BPtestXML.txt" && AddBackSlash

***********************
Local lcXML, loXMLAdapter, loXMLTable
Close Tables All
SET TALK OFF 

&&xmlfile="BPtestXML.txt"
&&xmlcontent = FILETOSTR(xmlfile)
xmlcontent = FILETOSTR(lcXMLFile)
 
lcXML = xmlcontent 

loXMLAdapter = CreateObject("XMLAdapter")

loXMLAdapter.LoadXML(lcXML,.F.,.T.)

? "XMLAdapter CREATED"
? "XML source file is " + lcXMLFile
&&	code to create a set of new tables from the xml file
*!*	For Each loXMLTable in loXMLAdapter.Tables
*!*	   loXMLTable.ToCursor()
*!*	  	COPY TO '\\Gmc\d\Stmt\Monterey\UB_Test_1231\XMLtoUB_Unstructured\' + (loXMLTable.Alias+".dbf")
*!*	ENDFOR

SET && Opens the Data Session window.

&&	code to append from *.xml to existing tables
*!*	For lnCount = 1 To Adir(laDbfs,"*.dbf")
*!*	   Use (laDbfs(lnCount,1)) In 0 Shared
*!*	   loXMLTable.ToCursor(.T.)
*!*	Endfor 

&& XMLAdapter.LoadXML( cXMLDocument [, lFile [, lValidateOnParse ]] )

Function GetPath()
   Lparameters tcPathalias, tlGlobal

   Local lcPathsAlias
   lcPathsAlias = iif(tlGlobal,"global","local")+"paths"

   Local lcPath
   If !Used(lcPathsAlias)
      If tlGlobal
         * get global path from local paths (tlGlobal = .F. explicitly)
         Use (GetPath("GLOBALPATHS",.F.) In 0 Alias (lcPathsAlias)
      Else
         Use (Justpath(Sys(16,0))+"\paths.dbf") In 0 alias (lcPathsAlias)
      Endif
   Endif
   Select cPath From (lcPathsAlias);
   Where cPathalias=tcPathalias;
   Into Cursor curPath
   If _tally = 1
      lcPath = curPath.cPath
   Else
      Messagebox("Path "+tcPathalias+" not found! Please add it to the appropriate paths.dbf")
      Suspend
   Endif

   Return lcPath
Endfunction
In the function definition, the following line gets and error:
Code:
   lcPathsAlias = iif(tlGlobal,"global","local")+"paths"
"Command contains unrecognized phrase/keyword."

Do you have any suggestions? I did set up both Db's and enter the data as instructed. Thanks!

smiletiniest.gif
Pete S
 
I don't know what's going on, but tlGlobal must be a boolean value, eg you must only pass in .T. or .F. or nothing (which make tlGlobal = .f.)

You may change the iif to a normal if:

Code:
IF tlGlobal
   lcPathsAlias = "globalpaths"
ELSE
   lcPathsAlias = "localpaths"
ENDIF

This may raise an error too, but maybe that error will be clearer in what is wrong.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top