Page 1 of 2
Parse XML [Solved]
Posted: Sat Apr 11, 2020 5:56 pm
by mocitymm
I am attempting for the first time with PB to load and parse a XML file, format as follows (loading from file and in string variable per the example below):
Code: Select all
<ClientConfig>
<SubAgents>
<SubAgent id="CTAGENT">
<Name>Altiris Client Task Agent</Name>
<GUID>{A8508496-ECA5-9197-E985-93FC4DF2837F}</GUID>
<ProgId>Altiris.ClientTaskAgent</ProgId>
<Version>8.5.4235</Version>
<Build>4235</Build>
<Path>/opt/altiris/notification/ctagent</Path>
<Is64bit>true</Is64bit>
</SubAgent>
<SubAgent id="CTSCHEDAGENT">
<Name>Altiris Client Task Scheduling Agent</Name>
<GUID>{68566E79-E211-B6EB-BFF2-9BA54305970B}</GUID>
<ProgId>Altiris.CTSchedulingAgent</ProgId>
<Version>8.5.4235</Version>
<Build>4235</Build>
<Path>/opt/altiris/notification/ctagent</Path>
<Is64bit>true</Is64bit>
</SubAgent>
<SubAgent id="CTBASEHANDLERS">
<Name>Altiris Base Task Handlers</Name>
<GUID>{FFB63A97-35C8-1445-02B0-54034E45B091}</GUID>
<ProgId>Altiris.BaseTaskHandlersAgent</ProgId>
<Version>8.5.4235</Version>
<Build>4235</Build>
<Path>/opt/altiris/notification/basetasks</Path>
<Is64bit>true</Is64bit>
</SubAgent>
</SubAgents>
</ClientConfig>
I've tried numerous examples on the board here, as example this one (which does work with the examples in code and I replaced the string text in the code to match my xml file construct and info):
viewtopic.php?f=13&t=73916&hilit=Parse+XML
but it's throwing an error of 'not well-formed (invalid token)' and nothing else to go on, I just need the Name, Version and Path information. I am converting from a completed Pascal project... and this driving me nutz.
If someone has the time to point me in the right direction with this problem, it would be greatly appreciated.
Regards,
-M
Re: Parse XML
Posted: Sat Apr 11, 2020 6:19 pm
by Kiffi
Replace </ClientConf> with </ClientConfig>
Greetings ... Peter
Re: Parse XML
Posted: Sat Apr 11, 2020 8:45 pm
by mocitymm
Kiffi wrote:Replace </ClientConf> with </ClientConfig>
Greetings ... Peter
That was a typo on my part for cut/paste on the forum, not in file or code.
-M
Re: Parse XML
Posted: Sat Apr 11, 2020 8:59 pm
by Kiffi
mocitymm wrote:That was a typo on my part for cut/paste on the forum, not in file or code.
The XML you posted has now been corrected and is therefore well-formed. No longer a problem.

Re: Parse XML
Posted: Sat Apr 11, 2020 9:14 pm
by mocitymm
Kiffi wrote:mocitymm wrote:That was a typo on my part for cut/paste on the forum, not in file or code.
The XML you posted has now been corrected and is therefore well-formed. No longer a problem.

Kiffi,
I appreciate your input but, it's not the issue at all. I will express again that was a typo on my part during a cut/paste to the forum.
The typo is not in the file or the code that it was tested with, the issue stays the same.
Try the xml in your code yourself. I've narrowed down what is possibly the issue: <SubAgent id="CTAGENT">, or <SubAgent id="CTSCHEDAGENT"> and or <SubAgent id="CTBASEHANDLERS">
I've used the ExtractXMLStructure and ExtractXMLList and both error out with the following: 'CTAGENT' or 'CTSCHEDAGENT' and or 'CTBASEHANDLERS' is not a valid operator.
If you know of way around that please let me know. The typo in the cut/paste is not the issue.
Regards,
-M
Re: Parse XML
Posted: Sat Apr 11, 2020 9:37 pm
by kenmo
You will have to post some code that demonstrates it, because the XML now loads fine for me too.
PB 5.72 Windows 32-bit
Code: Select all
; Saved example XML to ClientConfig.xml
If LoadXML(0, "ClientConfig.xml")
If XMLStatus(0) = #PB_XML_Success
Debug "OK" ; get OK
Else
Debug "Failed"
EndIf
Else
Debug "Failed"
EndIf
Re: Parse XML
Posted: Sat Apr 11, 2020 9:41 pm
by mocitymm
kenmo wrote:You will have to post some code that demonstrates it, because the XML now loads fine for me too.
PB 5.72 Windows 32-bit
Code: Select all
; Saved example XML to ClientConfig.xml
If LoadXML(0, "ClientConfig.xml")
If XMLStatus(0) = #PB_XML_Success
Debug "OK" ; get OK
Else
Debug "Failed"
EndIf
Else
Debug "Failed"
EndIf
Hey kenmo,
Load isn't the issue either, it's parsing it. XMLStatus() is a success return.
-M
Re: Parse XML
Posted: Sat Apr 11, 2020 10:24 pm
by Kiffi
You cannot use ExtractXMLStructure().
Instead, you must read the XML manually:
Code: Select all
EnableExplicit
Structure sSubAgent
Name.s
GUID.s
ProgId.s
Version.s
Build.s
Path.s
Is64bit.s
EndStructure
Structure sSubAgents
List SubAgent.sSubAgent()
EndStructure
Structure sClientConfig
SubAgents.sSubAgents
EndStructure
Define Xml.s
Xml = "<ClientConfig>" +
" <SubAgents>" +
" <SubAgent id='CTAGENT'>" +
" <Name>Altiris Client Task Agent</Name>" +
" <GUID>{A8508496-ECA5-9197-E985-93FC4DF2837F}</GUID>" +
" <ProgId>Altiris.ClientTaskAgent</ProgId>" +
" <Version>8.5.4235</Version>" +
" <Build>4235</Build>" +
" <Path>/opt/altiris/notification/ctagent</Path>" +
" <Is64bit>true</Is64bit>" +
" </SubAgent>" +
" <SubAgent id='CTSCHEDAGENT'>" +
" <Name>Altiris Client Task Scheduling Agent</Name>" +
" <GUID>{68566E79-E211-B6EB-BFF2-9BA54305970B}</GUID>" +
" <ProgId>Altiris.CTSchedulingAgent</ProgId>" +
" <Version>8.5.4235</Version>" +
" <Build>4235</Build>" +
" <Path>/opt/altiris/notification/ctagent</Path>" +
" <Is64bit>true</Is64bit>" +
" </SubAgent>" +
" <SubAgent id='CTBASEHANDLERS'>" +
" <Name>Altiris Base Task Handlers</Name>" +
" <GUID>{FFB63A97-35C8-1445-02B0-54034E45B091}</GUID>" +
" <ProgId>Altiris.BaseTaskHandlersAgent</ProgId>" +
" <Version>8.5.4235</Version>" +
" <Build>4235</Build>" +
" <Path>/opt/altiris/notification/basetasks</Path>" +
" <Is64bit>true</Is64bit>" +
" </SubAgent> " +
" </SubAgents>" +
"</ClientConfig>"
If ParseXML(0, xml)
If XMLStatus(0) = #PB_XML_Success
Define ClientConfig.sClientConfig
Define SubAgentNode = XMLNodeFromPath(MainXMLNode(0), "SubAgents/SubAgent")
While SubAgentNode
AddElement(ClientConfig\SubAgents\SubAgent())
ClientConfig\SubAgents\SubAgent()\Name = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Name"))
ClientConfig\SubAgents\SubAgent()\GUID = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "GUID"))
ClientConfig\SubAgents\SubAgent()\ProgId = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "ProgId"))
ClientConfig\SubAgents\SubAgent()\Version = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Version"))
ClientConfig\SubAgents\SubAgent()\Build = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Build"))
ClientConfig\SubAgents\SubAgent()\Path = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Path"))
ClientConfig\SubAgents\SubAgent()\Is64bit = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Is64bit"))
SubAgentNode = NextXMLNode(SubAgentNode)
Wend
FreeXML(0)
; Output:
ForEach ClientConfig\SubAgents\SubAgent()
Debug ClientConfig\SubAgents\SubAgent()\Name
Debug ClientConfig\SubAgents\SubAgent()\GUID
; and so on...
Next
Else
Debug "!XMLStatus()"
EndIf
Else
Debug "!ParseXML()"
EndIf
[/size]
P.S.: The question would have been resolved much faster if you had posted a piece
of your code and asked why it did not work.
Re: Parse XML
Posted: Sat Apr 11, 2020 10:47 pm
by mocitymm
Kiffi wrote:You cannot use ExtractXMLStructure().
Instead, you must read the XML manually:
Code: Select all
EnableExplicit
Structure sSubAgent
Name.s
GUID.s
ProgId.s
Version.s
Build.s
Path.s
Is64bit.s
EndStructure
Structure sSubAgents
List SubAgent.sSubAgent()
EndStructure
Structure sClientConfig
SubAgents.sSubAgents
EndStructure
Define Xml.s
Xml = "<ClientConfig>" +
" <SubAgents>" +
" <SubAgent id='CTAGENT'>" +
" <Name>Altiris Client Task Agent</Name>" +
" <GUID>{A8508496-ECA5-9197-E985-93FC4DF2837F}</GUID>" +
" <ProgId>Altiris.ClientTaskAgent</ProgId>" +
" <Version>8.5.4235</Version>" +
" <Build>4235</Build>" +
" <Path>/opt/altiris/notification/ctagent</Path>" +
" <Is64bit>true</Is64bit>" +
" </SubAgent>" +
" <SubAgent id='CTSCHEDAGENT'>" +
" <Name>Altiris Client Task Scheduling Agent</Name>" +
" <GUID>{68566E79-E211-B6EB-BFF2-9BA54305970B}</GUID>" +
" <ProgId>Altiris.CTSchedulingAgent</ProgId>" +
" <Version>8.5.4235</Version>" +
" <Build>4235</Build>" +
" <Path>/opt/altiris/notification/ctagent</Path>" +
" <Is64bit>true</Is64bit>" +
" </SubAgent>" +
" <SubAgent id='CTBASEHANDLERS'>" +
" <Name>Altiris Base Task Handlers</Name>" +
" <GUID>{FFB63A97-35C8-1445-02B0-54034E45B091}</GUID>" +
" <ProgId>Altiris.BaseTaskHandlersAgent</ProgId>" +
" <Version>8.5.4235</Version>" +
" <Build>4235</Build>" +
" <Path>/opt/altiris/notification/basetasks</Path>" +
" <Is64bit>true</Is64bit>" +
" </SubAgent> " +
" </SubAgents>" +
"</ClientConfig>"
If ParseXML(0, xml)
If XMLStatus(0) = #PB_XML_Success
Define ClientConfig.sClientConfig
Define SubAgentNode = XMLNodeFromPath(MainXMLNode(0), "SubAgents/SubAgent")
While SubAgentNode
AddElement(ClientConfig\SubAgents\SubAgent())
ClientConfig\SubAgents\SubAgent()\Name = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Name"))
ClientConfig\SubAgents\SubAgent()\GUID = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "GUID"))
ClientConfig\SubAgents\SubAgent()\ProgId = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "ProgId"))
ClientConfig\SubAgents\SubAgent()\Version = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Version"))
ClientConfig\SubAgents\SubAgent()\Build = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Build"))
ClientConfig\SubAgents\SubAgent()\Path = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Path"))
ClientConfig\SubAgents\SubAgent()\Is64bit = GetXMLNodeText(XMLNodeFromPath(SubAgentNode, "Is64bit"))
SubAgentNode = NextXMLNode(SubAgentNode)
Wend
FreeXML(0)
; Output:
ForEach ClientConfig\SubAgents\SubAgent()
Debug ClientConfig\SubAgents\SubAgent()\Name
Debug ClientConfig\SubAgents\SubAgent()\GUID
; and so on...
Next
Else
Debug "!XMLStatus()"
EndIf
Else
Debug "!ParseXML()"
EndIf
[/size]
P.S.: The question would have been resolved much faster if you had posted a piece
of your code and asked why it did not work.
Kiffi,
Thank you for the offer of help, the pointer on ExtractXMLStructure (is going to save me time and head banging, I appreciate it) however, your code won't work.
I am not writing the xml file only reading it, the xml file is an output of a service on the machine.
I can't change " to ' around SubAgent id='CTAGENT' (now if single quotes were native to the xml file, your code would work perfectly) otherwise, it generates the previous stated error:
'CTAGENT' or 'CTSCHEDAGENT' and or 'CTBASEHANDLERS' is not a valid operator
I appreciate the effort and when I said that I've tried numerous examples and included the link to the code that I tried, it was implied that this was the code that wasn't working.
I appreciate all the input from everyone. I will forego the conversion project since, I have it finished in Pascal which is working.
Regards,
-Mo
Re: Parse XML
Posted: Sat Apr 11, 2020 11:15 pm
by Kiffi
mocitymm wrote:I can't change " to ' around SubAgent id='CTAGENT' (now if single quotes were native to the xml file, your code would work perfectly)
Code: Select all
Xml = "<ClientConfig>" +
" <SubAgents>" +
" <SubAgent id=" + Chr(34) + "CTAGENT" + Chr(34) + ">" +
...
As written: If you don't show us your code, we can't help you.
Re: Parse XML
Posted: Sat Apr 11, 2020 11:36 pm
by mocitymm
Kiffi wrote:mocitymm wrote:I can't change " to ' around SubAgent id='CTAGENT' (now if single quotes were native to the xml file, your code would work perfectly)
Code: Select all
Xml = "<ClientConfig>" +
" <SubAgents>" +
" <SubAgent id=" + Chr(34) + "CTAGENT" + Chr(34) + ">" +
...
As written: If you don't show us your code, we can't help you.
Kiffi,
I've got a great idea... xml format (originally posted) drop it into a xml file on your hard drive as 'written' and that includes double quotes (") not single quotes (') and see if you can read the file.
Or you can leave the post as [Solved], I am not working this any more.
As much as I would like to convert the project, I am finding that the documentation/examples in PB too sparse or even better yet Pascal has made me completely lazy. I am sticking with lazy, it works from document and example to production code or it's a boat load more forgiving to idiots like me.
I do appreciate the effort, I do.
Regards,
-M
Re: Parse XML
Posted: Sat Apr 11, 2020 11:41 pm
by Kiffi
ok, I did my best. I'm out.
Re: Parse XML
Posted: Sun Apr 12, 2020 12:13 am
by mocitymm
Kiffi wrote:ok, I did my best. I'm out.
I know you did and it is appreciated. Thank you.
Pascal doesn't get hung up on the node attribute 'id' (because of double quotes) or the attribute at all, I can enumerate the 'SubAgent' nodes and perform my loop, parse the information I need and done. And with that xml file, there maybe 3 nodes or 15 depending on what it services are installed and active.
So, I would have to either install all 15 subagents or use a regex for the id attribute so I can parse the information that is there or not, code for non existent instances of that particular id attribute. In my head I am seeing a load of coding to do that. I assumed and imagined that it would be a little more simple than it was turning out to be. I coded everything in Pascal in a half day for the 8 different xml files and populated form components with the parsed information, my estimation on time for using PB is a little off.
I was eager to convert the project since I've completed about 40% of it and the size difference is amazing (from a Pascal binary of 40Mb to little under 3Mb for PureBasic - not fully converted), I don't use PB enough to get through it at the moment.
Thank you again for your help and effort.
Regards,
-M
Re: Parse XML
Posted: Sun Apr 12, 2020 5:59 pm
by kenmo
mocitymm wrote:Pascal doesn't get hung up on the node attribute 'id' (because of double quotes) or the attribute at all, I can enumerate the 'SubAgent' nodes and perform my loop, parse the information I need and done.
Hmm? You can do exactly that in PB. Basically what Kiffi's code is showing.
You just can't use ExtractXMLStructure to do it in one command, if the file's not formatted right for it.
But you don't *need* ExtractXMLStructure, it's just a helper, in fact the PB XML library originally didn't have it. You had to loop through nodes.
Double-quotes vs single-quotes doesn't matter. In PB it's just easier to write in XML with single-quotes since double-quotes wrap the entire string.
Re: Parse XML [Solved]
Posted: Sun Apr 12, 2020 9:07 pm
by HeX0R
Of course you could do an ExtractXMLStructure, or am I missing something here?
Code: Select all
While SubAgentNode
AddElement(ClientConfig\SubAgents\SubAgent())
ExtractXMLStructure(SubAgentNode, @ClientConfig\SubAgents\SubAgent(), sSubAgent)
SubAgentNode = NextXMLNode(SubAgentNode)
Wend