ScriptSpot

Forum topic · General Scripting

Manipulate XML file

By Budi G · 2013-09-17

Description

Hi ...

a bit stuck with this ...

in my case, I want to replace the old value with a new value via Dotnet

this is XML view

the value of the sphere is a target to be changed

what I want to do is simple,... replace a "sphere" value with a "plane"


--------------------------------------------------------------------------------------------------- Initial
--Load the xml assembly
dotNet.loadAssembly "system.xml"
--Create an xml document object.
xmlDoc=dotNetObject "system.xml.xmlDocument"

--Open the file in Max to see the file. 
filename="C:\\BGtest.xml" -- ((getDir #autoback)+"\\BGtest.xml")

--------------------------------------------------------------------------------------------------- Load document
	--Load the XML file.
	xmlDoc.load filename
--------------------------------------------------------------------------------------------------- read document
	--Check to make sure the xmlDoc has a root element. 
	docEle=xmlDoc.documentElement
	clearListener()
	format "Element Name: %\n\n" docEle.name

	--Check a target attribute value called name
	objNameStr=(docEle.ChildNodes.itemOf[0].GetAttributeNode "name").value
	format "Node Name: %\n\n" objNameStr
       
	--Check a target attribute value called class
	objClassStr=(docEle.ChildNodes.itemOf[0].GetAttributeNode "class").value
        format "Node class: %\n\n" objClassStr

--------------------------------------------------------------------------------------------------- Manipulate document
	--Want to replace "sphere" to "Plane"  but it's doesn't work correctly
	docEle.ChildNodes.itemOf[0].SetAttributeNode "name" "Plane001" --$.name
	docEle.ChildNodes.itemOf[0].SetAttributeNode "class" "Plane" --classOf $ as string

--------------------------------------------------------------------------------------------------- save and open document
xmlDoc.save filename
edit filename -- to see the result

so i tried but still not working

any suggestion ?

attached example xml...

thanks

Attachments
Comments (6)

Budi G · 2013-09-18

hi Branko...
thanks for some links and your scripts ;)

correct, I got the point of what I needed...

after checking your script, the problem can be solved


--Load the xml assembly
dotNet.loadAssembly "system.xml"
--Create an xml document object.
xmlDoc=dotNetObject "system.xml.xmlDocument"
 
--Open the file in Max to see the file. 
filename="C:\\BGtest.xml"
 
--------------------------------------------------------------------------------------------------- Load document
	--Load the XML file.
	xmlDoc.load filename
--------------------------------------------------------------------------------------------------- read document
	--Check to make sure the xmlDoc has a root element. 
	docEle=xmlDoc.documentElement
	clearListener()
	format "Element Name: %\n\n" docEle.name
 
	--Check a target attribute value called name
	objNameStr=(docEle.ChildNodes.itemOf[0].GetAttributeNode "name").value
	format "Node Name: %\n\n" objNameStr
 
	--Check a target attribute value called class
	objClassStr=(docEle.ChildNodes.itemOf[0].GetAttributeNode "class").value
        format "Node class: %\n\n" objClassStr
 
--------------------------------------------------------------------------------------------------- Manipulate document
	--Reject this code
	--docEle.ChildNodes.itemOf[0].SetAttributeNode "name" "Plane001" --$.name
	--docEle.ChildNodes.itemOf[0].SetAttributeNode "class" "Plane" --classOf $ as string
	
	-- Correct, to replace "sphere" with "Plane"
	docEle.ChildNodes.Item[0].Attributes.ItemOf["name"].value = "Plane001"
	docEle.ChildNodes.Item[0].Attributes.ItemOf["class"].value = "Plane"
 
--------------------------------------------------------------------------------------------------- save and open document
xmlDoc.save filename
edit filename -- to see the result

glad to see the results

thank you very much man

barigazy · 2013-09-18

My pleasure.
BTW using XPath you can easely and fast edit any xml file.
I tried to use it but without luck. Maybe next time :)

Budi G · 2013-09-19

sounds a good thing...
but I hold information about XPath first.
a new language is enough to make me busy for a while. :D
I'm currently finishing another script, yeah maybe next time.

barigazy · 2013-09-17

Maybe this method will help

--Collect scene nodes and classes
objsList = for o in geometry where o != TargetObject collect #(o.name, getClassName o)
--xml file (change if you want)
xmlFileName = getdir #scripts + "\\BGtest.xml"
--With this fn you can easely create xml elements
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
)
-- store all data in xml
fn saveXML xmlFile: data: = if objsList.count != 0 do
(
local xmldoc = dotNetObject "System.Xml.XmlDocument"
root = xmlCreator dnXML:xmldoc prtNode:xmldoc tagName:"Node_Collector" \
attArr:#(#("version","1.0"), #("author","Budi Gunawan"), #("website","http://bg-script.blogspot.com/"))
nodes = xmlCreator dnXML:xmldoc prtNode:root tagName:"Nodes_List"
comment_1 = xmlCreator dnXML:xmldoc prtNode:nodes tagName:"This list represents all scene geometry nodes" make:#xmlComment
for i = 1 to data.count do
(
xmlCreator dnXML:xmldoc prtNode:nodes tagName:("n_" + ((i-1) as String)) \
attArr:#(#("name", data[i][1]), #("class", (data[i][2] as String)))
)
info = xmlCreator dnXML:xmldoc prtNode:root tagName:"Object_Info"
comment_2 = xmlCreator dnXML:xmldoc prtNode:info tagName:"Usual Scene Info." make:#xmlComment
count = xmlCreator dnXML:xmldoc prtNode:info tagName:"Scene_Objects_Count" innerTxt:(objsList.count as String)
ltime = xmlCreator dnXML:xmldoc prtNode:info tagName:"Local_Time" innerTxt:localtime
xmldoc.Save xmlFile
edit xmlFile
)
saveXML xmlFile:xmlFileName data:objsList

barigazy · 2013-09-17

Now we need to load xml


-- load xml
fn getValueByRootEle rootEl: tagName: attName: =
(
	local idx = undefined
	for i = 1 to rootEl.ChildNodes.count-1 where rootEl.ChildNodes.ItemOf[i].name == tagName do idx = i
	if idx != null then rootEl.ChildNodes.Item[idx].Attributes.ItemOf[attName].value else idx
)
xmlFileName = getdir #scripts + "\\BGtest.xml"
xmldoc = dotNetObject "System.Xml.XmlDocument"
xmldoc.Load xmlFileName
rootEle = xmldoc.DocumentElement
nList = rootEle.Item["Nodes_List"]
oInfo = rootEle.Item["Object_Info"]
-- get some values from xml file
n2class = getValueByRootEle rootEl:nList tagName:"n_2" attName:"class"
n3name = getValueByRootEle rootEl:nList tagName:"n_3" attName:"name"
oc = (oInfo.Item["Scene_Objects_Count"].InnerText) as Integer
lt = (oInfo.Item["Local_Time"].InnerText)

According to this u can create new fn for setting new values for docElements with
couple attributes.(similar to "getValueByRootEle" fn) :)
To change let say *Scene_Objects_Count* U can use this

-- close first file if is opened in mxs editor
oInfo.Item["Scene_Objects_Count"].InnerText = "1856"
xmldoc.Save xmlFileName

barigazy · 2013-09-17

Also you can look inside code of *ScriptRun* tool where I used similar method for storing some script settings.
Another useful method can be achived with XPath