Parse XML [Solved]

Just starting out? Need help? Post your questions and find answers here.
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Parse XML [Solved]

Post 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
Last edited by mocitymm on Sat Apr 11, 2020 10:47 pm, edited 2 times in total.
User avatar
Kiffi
Addict
Addict
Posts: 1510
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Parse XML

Post by Kiffi »

Replace </ClientConf> with </ClientConfig>

Greetings ... Peter
Hygge
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Re: Parse XML

Post 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
User avatar
Kiffi
Addict
Addict
Posts: 1510
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Parse XML

Post 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. Image
Hygge
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Re: Parse XML

Post 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. Image
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
User avatar
kenmo
Addict
Addict
Posts: 2069
Joined: Tue Dec 23, 2003 3:54 am

Re: Parse XML

Post 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
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Re: Parse XML

Post 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
User avatar
Kiffi
Addict
Addict
Posts: 1510
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Parse XML

Post 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.
Hygge
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Re: Parse XML

Post 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
User avatar
Kiffi
Addict
Addict
Posts: 1510
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Parse XML

Post 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.
Hygge
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Re: Parse XML

Post 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. :P

I do appreciate the effort, I do.

Regards,

-M
User avatar
Kiffi
Addict
Addict
Posts: 1510
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Parse XML

Post by Kiffi »

ok, I did my best. I'm out.
Hygge
mocitymm
User
User
Posts: 37
Joined: Wed Feb 08, 2017 6:56 pm

Re: Parse XML

Post 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. :shock:

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
User avatar
kenmo
Addict
Addict
Posts: 2069
Joined: Tue Dec 23, 2003 3:54 am

Re: Parse XML

Post 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.
User avatar
HeX0R
Addict
Addict
Posts: 1227
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: Parse XML [Solved]

Post 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
Post Reply