Page 1 of 1

Can the XML lib handle this?

Posted: Sun Mar 14, 2021 3:22 am
by kpeters58
...
<VersionInfoKeys>
<VersionInfoKeys Name="CompanyName">ACME Software Inc.</VersionInfoKeys>
<VersionInfoKeys Name="FileDescription">ACME TimeCard Import</VersionInfoKeys>
<VersionInfoKeys Name="InternalName">ACME_TcImp.dll</VersionInfoKeys>
<VersionInfoKeys Name="LegalCopyright">Copyright © 2021 ACME Software Group Inc.</VersionInfoKeys>
<VersionInfoKeys Name="ProductName">ACME Import Module</VersionInfoKeys>
<VersionInfoKeys Name="ProductVersion">2.10.1.1</VersionInfoKeys>
</VersionInfoKeys>
...
Fairly easy to get the first attribute line - but what if I was after the 'LegalCopyright' entry? What am I missing?

Code: Select all

    *node = XMLNodeFromPath(RootXMLNode(#XML), "Project/ProjectExtensions/BorlandProject/Delphi.Personality/VersionInfoKeys/VersionInfoKeys")
    If (*node)
      Debug GetXMLAttribute(*node, "Name")
      Debug GetXMLNodeText(*node)
    ; SetXMLAttribute(*Node, "Name", "new_string")
    Else
      Debug "No such node!"
    EndIf

Re: Can the XML lib handle this?

Posted: Sun Mar 14, 2021 8:43 am
by TI-994A
kpeters58 wrote:
...
<VersionInfoKeys>
<VersionInfoKeys Name="CompanyName">ACME Software Inc.</VersionInfoKeys>
<VersionInfoKeys Name="FileDescription">ACME TimeCard Import</VersionInfoKeys>
<VersionInfoKeys Name="InternalName">ACME_TcImp.dll</VersionInfoKeys>
<VersionInfoKeys Name="LegalCopyright">Copyright © 2021 ACME Software Group Inc.</VersionInfoKeys>
<VersionInfoKeys Name="ProductName">ACME Import Module</VersionInfoKeys>
<VersionInfoKeys Name="ProductVersion">2.10.1.1</VersionInfoKeys>
</VersionInfoKeys>
...
Fairly easy to get the first attribute line - but what if I was after the 'LegalCopyright' entry?
The XML tree must be iterated through with the NextXMLNode() function, like so:

Code: Select all

; create an example XML tree as per OP 
;
xml = CreateXML(#PB_Any) 
mainNode = CreateXMLNode(RootXMLNode(xml), "VersionInfoKeys") 

Restore xmlData
For i = 0 To 5
  Read.s subNodeID$
  Read.s subNodeValue$
  item = CreateXMLNode(mainNode, "VersionInfoKeys") 
  SetXMLAttribute(item, "Name", subNodeID$) 
  SetXMLNodeText(item, subNodeValue$)
Next i

DataSection
xmlData:
  Data.s "CompanyName", "ACME Software Inc."
  Data.s "FileDescription", "ACME TimeCard Import"
  Data.s "InternalName", "ACME_TcImp.dll"
  Data.s "LegalCopyright", "Copyright © 2021 ACME Software Group Inc."
  Data.s "ProductName", "ACME Import Module"
  Data.s "ProductVersion", "2.10.1.1"
EndDataSection


; iterate through the XML tree and extract the values
;
*node = ChildXMLNode(MainXMLNode(xml))
While *node   
  Debug GetXMLAttribute(*node, "Name") + ": " + GetXMLNodeText(*node)
  *node = NextXMLNode(*node)  
Wend 

Re: Can the XML lib handle this?

Posted: Sun Mar 14, 2021 2:58 pm
by helpy
Quote from above:

Code: Select all

<VersionInfoKeys>
  <VersionInfoKeys Name="CompanyName">ACME Software Inc.</VersionInfoKeys>
  ...
  <VersionInfoKeys Name="ProductVersion">2.10.1.1</VersionInfoKeys>
</VersionInfoKeys>
I would change the child keys of VersionInfoKeys from VersionInfoKeys to VersionInfoKey:

Code: Select all

<VersionInfoKeys>
  <VersionInfoKey Name="CompanyName">ACME Software Inc.</VersionInfoKey>
  ...
  <VersionInfoKey Name="ProductVersion">2.10.1.1</VersionInfoKey>
</VersionInfoKeys>

Re: Can the XML lib handle this?

Posted: Sun Mar 14, 2021 4:10 pm
by kpeters58
helpy wrote:Quote from above:

Code: Select all

<VersionInfoKeys>
  <VersionInfoKeys Name="CompanyName">ACME Software Inc.</VersionInfoKeys>
  ...
  <VersionInfoKeys Name="ProductVersion">2.10.1.1</VersionInfoKeys>
</VersionInfoKeys>
I would change the child keys of VersionInfoKeys from VersionInfoKeys to VersionInfoKey:

Code: Select all

<VersionInfoKeys>
  <VersionInfoKey Name="CompanyName">ACME Software Inc.</VersionInfoKey>
  ...
  <VersionInfoKey Name="ProductVersion">2.10.1.1</VersionInfoKey>
</VersionInfoKeys>

So would I - but since this is part of a Delphi project file, there is little I can do to make this right ... :(

Re: Can the XML lib handle this?

Posted: Sun Mar 14, 2021 4:46 pm
by kpeters58
Thanks, I had tried that but I made the crucial mistake of not realizing that NextXMLNode returns the next node and not just a boolean value

Re: Can the XML lib handle this?

Posted: Sun Mar 14, 2021 8:13 pm
by helpy
A little test example:

Code: Select all

EnableExplicit

Procedure CreateXmlExample()
	Protected xml
	Protected node, i, item
	Protected subNodeID.s, subNodeValue.s
	; create an example XML tree as per OP
	; 
	xml = CreateXML(#PB_Any)
	node = CreateXMLNode(RootXMLNode(xml), "Project")
	node = CreateXMLNode(node, "ProjectExtensions")
	node = CreateXMLNode(node, "BorlandProject")
	node = CreateXMLNode(node, "Delphi.Personality")
	node = CreateXMLNode(node, "VersionInfoKeys")
	
	Restore xmlData
	For i = 0 To 5
		Read.s subNodeID
		Read.s subNodeValue
		item = CreateXMLNode(node, "VersionInfoKeys")
		SetXMLAttribute(item, "Name", subNodeID)
		SetXMLNodeText(item, subNodeValue)
	Next i
	
	ProcedureReturn xml
EndProcedure

Procedure XMLNodeFromPathWithAttribute(ParentNode, Path.s, AttributeName.s, AttributeValue.s)
	Protected nthIndex, nthNode, nthPath.s
	Protected nodeResult
	
	Repeat
		nthIndex + 1
		nthPath = path + "[" + Str(nthIndex) + "]"
		nthNode = XMLNodeFromPath(ParentNode, nthPath)
		If Not nthNode : Break : EndIf
		If GetXMLAttribute(nthNode, AttributeName) = AttributeValue
			nodeResult = nthNode
			Break
		EndIf
	ForEver
		
	ProcedureReturn nodeResult
EndProcedure


Define xmlExample, i, infoNode, subNodeID.s, subNodeValue.s
Define VersionKeys

xmlExample = CreateXmlExample()

Debug "First Test"
Restore xmlData
For i = 0 To 5
	Read.s subNodeID
	Read.s subNodeValue
	infoNode = XMLNodeFromPathWithAttribute(RootXMLNode(xmlExample),
	                                        "Project/ProjectExtensions/BorlandProject/Delphi.Personality/VersionInfoKeys/VersionInfoKeys",
	                                        "Name", subNodeID)
	Debug LSet(subNodeID + " ", 20, ".") + " " + GetXMLNodeText(infoNode)
Next i

Debug ""
Debug "Second Test"
VersionKeys = XMLNodeFromPath(RootXMLNode(xmlExample), 
                              "/Project/ProjectExtensions/BorlandProject/Delphi.Personality/VersionInfoKeys")
If VersionKeys
	Restore xmlData
	For i = 0 To 5
		Read.s subNodeID
		Read.s subNodeValue
		infoNode = XMLNodeFromPathWithAttribute(VersionKeys, "VersionInfoKeys", "Name", subNodeID)
		Debug LSet(subNodeID + " ", 20, ".") + " " + GetXMLNodeText(infoNode)
	Next i
EndIf

DataSection
	xmlData:
	Data.s "CompanyName", "ACME Software Inc."
	Data.s "FileDescription", "ACME TimeCard Import"
	Data.s "InternalName", "ACME_TcImp.dll"
	Data.s "LegalCopyright", "Copyright © 2021 ACME Software Group Inc."
	Data.s "ProductName", "ACME Import Module"
	Data.s "ProductVersion", "2.10.1.1"
EndDataSection