XML using samples

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

Thread Tools Search this Thread Display Modes
Old 04 April 2013   #1
XML using samples

I want to start a new thread where everyone free to post good samples of XML using. and of course everyone free to ask and answer questions.

here is my first sample... how to store and load nodes list. i store all scene dummies, their name, parent name, position and box size. reading a file i restore whole data...

  fn saveDummyFile filename: = 
  	if filename == unsupplied do filename = getSaveFilename caption:"Save Dummy List File" types:"Dummy List (.xml)|*.xml"
  	if filename != undefined do
  	if iskindof (doc = dotnetobject "System.Xml.XmlDocument") dotnetobject do
  		if getfilenametype filename == "" do filename += ".xml"
  		nodes = for d in (getclassinstances dummy) collect (refs.dependentnodes d firstonly:on)
  		doc.AppendChild (doc.CreateComment "Dummy List. Version 1.0")
  		doc.AppendChild (doc.CreateComment ("File: " + maxfilepath + maxfilename))
  		doc.AppendChild (doc.CreateComment ("Creation Date: " + localtime))
  		doc.AppendChild (doc.CreateWhitespace "\n")
  		doc.AppendChild (xnodes = doc.CreateElement "nodes")
  		xnodes.SetAttribute "count" (nodes.count as string)
  		for node in nodes do
  			xnodes.AppendChild (xnode = doc.CreateElement "node")
  			xnode.SetAttribute "node" node.name
  			xnode.SetAttribute "parent" (if node.parent == undefined then "" else node.parent.name)
  			xnode.SetAttribute "pos" (node.pos as string)
  			xnode.SetAttribute "boxsize" (node.boxsize as string)
  		doc.Save filename
  		-- edit filename
  fn loadDummyFile filename: = 
  	if filename == unsupplied do filename = getOpenFilename caption:"Load Dummy List File" types:"Dummy List (.xml)|*.xml"
  	if iskindof filename string and doesfileexist filename do
  	if iskindof (doc = dotnetobject "System.Xml.XmlDocument") dotnetobject do
  		doc.Load filename
  		local xnodes = doc.selectnodes "//node"
  		local nodes = for k=0 to xnodes.count-1 collect
  			xnode = xnodes.item[k]
  			name = xnode.getattribute "node"
  			parent = xnode.getattribute "parent"
  			pos = execute (xnode.getattribute "pos")
  			boxsize = execute (xnode.getattribute "boxsize")
  			d = dummy name:name pos:pos boxsize:boxsize
  			#(d, parent)
  		for n in nodes do if (p = getnodebyname n[2]) != undefined do n[1].parent = p
  -- create test scene:
  	delete objects
  	nodes = #()
  	for k=1 to 200 do
  		d = dummy pos:(random [-40,-40,-40] [40,40,40]) boxsize:(random [1,1,1] [10,10,10])
  		if (i = random 0 nodes.count) > 1 do d.parent = nodes[i] 
  		append nodes d
  -- save scene
  _dummyfile = saveDummyFile()
  -- reset scene
  resetmaxfile #noPrompt 
  -- load nodes
  loadDummyFile filename:_dummyfile

as you see i also save some extra data with file: data type, scene filename, and date of creation. these can help me later in any case.

with save and load functions i provide two methods to define filename. you can supply it as optional parameter, or manually set using file browser.

if you are new to XML data try to understand how this sample works first. later i will show the problems of this method. and everyone free to point me on any found problems and shortcomings.

Last edited by denisT : 04 April 2013 at 06:30 PM.
Old 04 April 2013   #2
Very nice and simple example.
I post from previous thread my snippet for storing some script settings

  local okToShow = true
  dotnet.loadAssembly "system.xml" 
  struct sr_Settings_struct (lvDataArr, locX, locY, ms, mse, mcr, mxsArr, mxsENArr, mxsFav)
  struct sr_XML_struct
 	 sioDir = dotNetClass "System.IO.Directory",
 	 sioFile = dotNetClass "System.IO.File",
 	 sysStr = dotNetClass "System.String",
 	 fn compareFNames arr str ignoreCase:true multi:true = 
 		 if multi then (for p in 1 to arr.count where (sysStr.Compare arr[p][2] str ignoreCase) == 0 collect p).count
 		 else (for p in 1 to arr.count where (sysStr.Compare arr[p] str ignoreCase) == 0 collect p).count
 	 fn isValidXML file =
 		 try ((dotNetObject "System.Xml.XmlDocument").Load file == undefined)
 		 catch (okToShow = false ; ((trimleft ((s=filterstring (getCurrentException()) ":")[s.count]) " ")+" Do you want to edit 'srSettings.xml' ?"))
 	 fn xmlCreator dnXML: prtNode: tagName: innerTxt: attArr: make:#xmlElement =
 		 local tag = if make != #xmlComment then (dnXML.createElement tagName) else (dnXML.createComment tagName)
 		 prtNode.AppendChild tag
 		 if innerTxt != unsupplied do tag.InnerText = innerTxt
 		 if attArr != unsupplied do (for i = 1 to attArr.count do tag.SetAttribute attArr[i][1] attArr[i][2]) ; tag
 	 fn getXMLvalue dnXML: tagName: type: =
 		 local val = (dnXML.selectNodes tagName).ItemOf[0].InnerText
 		 if type != unsupplied then val as type else val
 	 fn saveXML xmlFile pX: pY: msExt: mseExt: mcrExt: dirArr: favArr: =
 		 xmldoc = dotNetObject "System.Xml.XmlDocument"
 		 sRun = xmlCreator dnXML:xmldoc prtNode:xmldoc tagName:"ScriptRun" \
 		 attArr:#(#("version","1.1a"), #("author","Branko Zivkovic"), #("email","barigazy@hotmail.com"))
 		 sPaths = xmlCreator dnXML:xmldoc prtNode:sRun tagName:"FolderPaths"
 		 cmt_sPaths = xmlCreator dnXML:xmldoc prtNode:sPaths tagName:"Child elements of the *FolderPaths* element tags (<fp_0 ... />, <fp_1 .../> etc.)" make:#xmlComment
 		 for i = 1 to dirArr.count do
 			 fpe = xmlCreator dnXML:xmldoc prtNode:sPaths tagName:("fp_" + ((i-1) as String)) \
 			 attArr:#(#("path", dirArr[i][2]), #("use_subfolders", (dirArr[i][1] as String)))
 		 sSett = xmlCreator dnXML:xmldoc prtNode:sRun tagName:"ScriptSettings"
 		 sLocX = xmlCreator dnXML:xmldoc prtNode:sSett tagName:"location_x" innerTxt:(pX as String)
 		 sLocY = xmlCreator dnXML:xmldoc prtNode:sSett tagName:"location_y" innerTxt:(pY as String)
 		 sMS = xmlCreator dnXML:xmldoc prtNode:sSett tagName:"use_ms" innerTxt:(msExt as String)
 		 sMSE = xmlCreator dnXML:xmldoc prtNode:sSett tagName:"use_mse" innerTxt:(mseExt as String)
 		 sMCR = xmlCreator dnXML:xmldoc prtNode:sSett tagName:"use_mcr" innerTxt:(mcrExt as String)
 		 sFav = xmlCreator dnXML:xmldoc prtNode:sRun tagName:"FavoriteScripts"
 		 cmt_sFav = xmlCreator dnXML:xmldoc prtNode:sFav tagName:"Child elements of the *FavoriteScripts* element tags (<fs_0 ... </fs_0>, <fs_1 ... </fs_1> etc.)" make:#xmlComment
 		 if favArr.count != 0 do
 			 favArr = for s in favArr where sioFile.Exists s collect s
 			 if favArr.count != 0 do (for i = 1 to favArr.count do xmlCreator dnXML:xmldoc prtNode:sFav tagName:("fs_" + ((i-1) as String)) innerTxt:(favArr[i]))
 		 xmldoc.Save xmlFile
 	 fn loadXML xmlFile = if (v=isValidXML xmlFile) != true then (if queryBox v title:"srSettings.xml Error Message" beep:false do edit xmlFile) else 
 		 local lvItms = #(), xpos, ypos, useMS, useMSE, useMCR, mxsFiles = #(), mxsFilesEN = #(), mxsFavorites = #()
 		 xmldoc = dotNetObject "System.Xml.XmlDocument"
 		 sioSOpt = dotNetClass "System.IO.SearchOption"
 		 xmldoc.Load xmlFile
 		 rootEle = xmldoc.DocumentElement
 		 fp = rootEle.Item["FolderPaths"]
 		 ss = rootEle.Item["ScriptSettings"]
 		 fs = rootEle.Item["FavoriteScripts"]
 		 if fp.ChildNodes.count == 0 then lvItms = #(#(false, (getDir #scripts))) else
 			 for i = 1 to fp.ChildNodes.count-1 do
 				 usf = fp.ChildNodes.ItemOf[i].Attributes.ItemOf["use_subfolders"].value as BooleanClass
 				 dir = fp.ChildNodes.ItemOf[i].Attributes.ItemOf["path"].value
 				 if sioDir.Exists dir do append lvItms #(usf,dir)
 		 xpos = (ss.Item["location_x"].InnerText) as Integer
 		 ypos = (ss.Item["location_y"].InnerText) as Integer
 		 useMS = (ss.Item["use_ms"].InnerText) as BooleanClass
 		 useMSE = (ss.Item["use_mse"].InnerText) as BooleanClass
 		 useMCR = (ss.Item["use_mcr"].InnerText) as BooleanClass
 		 if lvItms.count != 0 do
 			 stateArr = #(useMS, useMSE, useMCR)
 			 extArr = #("*.ms", "*.mse", "*.mcr")
 			 for i = 1 to lvItms.count do
 				 filtOpt = if lvItms[i][1] then sioSOpt.AllDirectories else sioSOpt.TopDirectoryOnly
 				 for s = 1 to 3 where stateArr[s] do join mxsFiles (sioDir.GetFiles lvItms[i][2] extArr[s] filtOpt)
 			 mxsFiles = makeUniqueArray mxsFiles
 			 mxsFilesEN = for f in mxsFiles collect #(getFilenameFile f, toLower (trimleft (getFilenameType f) "."))
 			 if fs.ChildNodes.count > 1 do
 				 for i = 1 to fs.ChildNodes.count-1 where sioFile.Exists (fs.Item[("fs_" + (i-1) as string)].InnerText) do append mxsFavorites (fs.Item[("fs_" + (i-1) as string)].InnerText)
 					 fsc = getXMLvalue dnXML:xmldoc tagName:("//fs_" + i as String)
 					 if mxsFavorites.count == 0 then (if sioFile.Exists fsc do append mxsFavorites fsc)
 					 else (if sioFile.Exists fsc and (compareFNames mxsFavorites fsc multi:false) != 1 do append mxsFavorites fsc)					
 			 srSETT = sr_Settings_struct lvDataArr:lvItms locX:xpos locY:ypos ms:useMS mse:useMSE mcr:useMCR mxsArr:mxsFiles mxsENArr:mxsFilesEN mxsFav:mxsFavorites
 	 on create do
 		 xmlFile = getdir #expression + "\\srSettings.xml"
 		 if sioFile.Exists xmlFile then loadXML xmlFile else
 			 local posX = ((dotNetClass "Screen").PrimaryScreen.WorkingArea.Width/2) - 120
 			 local posY = ((dotNetClass "Screen").PrimaryScreen.WorkingArea.Height/2) - 11
 			 saveXML xmlFile pX:posX pY:posY msExt:true mseExt:true mcrExt:false dirArr:#(#(false, (getDir #scripts))) favArr:#()
 			 loadXML xmlFile

Now questions:
#1 Can you explain Normalize method for XML Document object?
#2 What's good or bad in my method?
#3 As thexmlMtlExporter is not exposed can you shows as some workaround for storing ei
export-import material to XML format? I know that some maps properties are not exposed also but I think that the XMLMaterial isbetter way for soring mats then MaterialLibrary (I can't open *.mat in previous version of max).
#4 XPath methods or xmlDocument methods which one is better?

By the way thank you for triggered this topic.
Looking in the right side. [bgaTools]

Last edited by gazybara : 04 April 2013 at 06:27 PM.
Old 04 April 2013   #3
Originally Posted by gazybara: #1 Can you explain Normalize method for XML Document object?

in my sample it doesn't make sense. i've made the snippet using some my other code. so it's useless thing in our case.
Old 04 April 2013   #4
denis, why do you create a System.Xml.XmlDocument and then immediatly compare it to a dotnetobject ?? seems redundant to me?
Old 04 April 2013   #5
Originally Posted by Gravey: denis, why do you create a System.Xml.XmlDocument and then immediatly compare it to a dotnetobject ?? seems redundant to me?

it's from old code... it was a time when not all versions of max (.net) supported System.Xml.XmlDocumen... and (dotnetobject "System.Xml.XmlDocumen") returned undefined. you are right. today this check is obsolete.
Old 04 April 2013   #6
Is it better to use structure for storing object data?
Old 04 April 2013   #7
Here is my codes for converting data between Treeview and XML :
	fn RecurseTVToXML XmlDoc TVNd XmlNd  =
		NewXmlNd = XmlDoc.createElement TVNd.Name
		XmlNd.appendChild NewXmlNd
		for i=0 to TvNd.Nodes.count-1 do RecurseTVToXML XmlDoc TvNd.Nodes.Item[i] NewXmlNd 
	fn TVToXML TheTV XmlFile = 
		if TheTV!= undefined then
			XmlDoc=dotNetObject "system.xml.xmlDocument"
			RecurseTVToXML XmlDoc TheTV XmlDoc 
			XmlDoc.save XmlFile

	fn RecurseXMLToTV XmlNd TVNd  = 
		NewTVNd = (dotNetObject "System.Windows.Forms.TreeNode" (XmlNd.Name)) 
		NewTVNd.name = (XmlNd.Name)
		TVNd.nodes.add NewTVNd 
		for i=0 to XmlNd.childnodes.count-1 do RecurseXMLToTV XmlNd.childnodes.itemof[i] NewTVNd  
	fn XMLToTV XmlFile TheTV  =
		if XmlFile!= undefined and TheTV!= undefined and doesFileExist XmlFile then
			XmlDoc=dotNetObject "system.xml.xmlDocument"
			XmlDoc.load XmlFile
			for i=0 to docEle.childnodes.count-1 do RecurseXMLToTV docEle.childnodes.itemof[i] TheTV 
Old 05 May 2013   #8
As we can't use LINQ to XML to read xml files, one alternative is to use Xpath. Here's a sample to get the max command panel height from the cui config file, which would be a ball ache to get otherwise.

fn getCommandPanelHeight =
xmlDoc = dotNetObject "system.xml.xmlDocument"
xmlDoc.load (cui.getConfigFile())
CmdNode = xmlDoc.selectNodes "//Window[@name='Command Panel']/DRect/@bottom|//Window[@name='Command Panel']/DRect/@top"
if cmdNode != undefined and cmdNode.count == 2 then
	(CmdNode.itemof[1].value as integer) - (CmdNode.itemof[0].value as integer) 
else undefined

there's some other examples on KlaasNienhuis's blog

as well as a great intro here

Read my technical blog - lonerobot.net
Old 05 May 2013   #9
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
Thread Closed share thread

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Society of Digital Artists

Powered by vBulletin
Copyright ©2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump

All times are GMT. The time now is 03:24 AM.

Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.