------------------------------------------------------------------------------ -- -- xml2.ms -- MaxScript XML Reader/Writer -- -- David Muir -- Edit: Luke Openshaw -- -- Uses .Net 2.0 framework (installed with Max) -- ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Globals ------------------------------------------------------------------------------ dotnet.LoadAssembly "System.Xml.dll" ------------------------------------------------------------------------------ -- Structure Definitions ------------------------------------------------------------------------------ struct XmlElement ( tagName = "", children = #(), attrs = dotnetobject "RSG.MaxUtils.MaxDictionary", textValue = "", fn findChild withName:undefined withAttribute:undefined = ( if undefined!=withName then for c in children where (c.tagname==withName) do return c if undefined!=withAttribute then for c in children where (c.attrs.ContainsKey withAttribute) do return c return undefined ) ) struct XmlDocument ( ------------------------------------------------------------------------------------ -- PUBLIC MEMBER DATA ------------------------------------------------------------------------------------ -- -- .Net System.Xml.XmlDocument Object -- -- See http://msdn2.microsoft.com/en-us/library/system.xml.xmldocument.aspx for -- documentation on methods and properties for node manipulation. -- document, maxXmlObject, ------------------------------------------------------------------------------------ -- CONSTANTS ------------------------------------------------------------------------------------ XmlNodeType = dotNetClass "System.Xml.XmlNodeType", ------------------------------------------------------------------------------------ -- PUBLIC METHODS ------------------------------------------------------------------------------------ -- FHT: I removed the garbage collection, because it was causing huge overheads on multiple small xml exports (textures) fn Release = ( if undefined!=document then ( document = undefined ) ), -- call this before you start any I/O operations fn init force:false = ( Release() document = dotNetObject "System.Xml.XmlDocument" local cpi = document.createProcessingInstruction ("xml") ("version=\"1.0\" encoding = \"UTF-8\"") document.AppendChild cpi ), -- save the in-memory xml document to file fn save xmlDocName = ( try( if( RsFileExists xmlDocName ) then (setFileAttribute xmlDocName #readOnly false) document.save xmlDocName Release() true )catch( msg = "Problem saving XmlDocument: \"" + xmlDocName + "\" Exception: " + getCurrentException(); gRsUlog.LogError msg context:xmlDocName Release() false ) ), -- create an xmlnode fn createnode type nodename namespace = ( if matchPattern nodename pattern:"* *" then ( gRsUlog.LogError ("Trying to create an xml element with spaces in its name: \""+nodename as string+"\"") nodename = substituteString nodename " " "_" ) xmlnode = document.createnode type nodename namespace xmlnode ), fn createTextNode thetext = ( xmlnode = document.createTextNode (thetext as string) xmlnode ), -- create an xmlattribute fn createattribute attrname attributeValue:undefined = ( if matchPattern attrname pattern:"* *" then ( gRsUlog.LogError ("Trying to create an xml element with spaces in its name: \""+attrname as string+"\"") attrname = substituteString attrname " " "_" ) xmlattr = document.createattribute attrname if undefined!=attributeValue then xmlattr.value = attributeValue as string xmlattr ), -- create an xmlelement fn createelement elemname appendTo:undefined attrs:undefined value:undefined = ( if matchPattern elemname pattern:"* *" then ( gRsUlog.LogError ("Trying to create an xml element with spaces in its name: \""+elemname as string+"\"") elemname = substituteString elemname " " "_" ) xmlelem = document.createelement elemname if undefined!=appendTo then appendTo.appendChild xmlelem if undefined!=attrs then ( for pair in attrs do ( xmlelem.SetAttribute pair[1] (pair[2] as string) ) ) if undefined!=value then ( local txtNode = createTextNode value xmlelem.appendChild txtNode ) return xmlelem ), -- create an xmlcomment fn createcomment thetext = ( xmlcomment = document.createcomment thetext xmlcomment ), -- remove a node fn removechild root node = ( root.removechild node ), fn ParseElementRec elem = ( local theType = elem.GetType() local elemClass = theType.name local maxElem = undefined if elemClass=="XmlDocument" then ( maxElem = XmlElement() maxElem.tagName = elem.name ) else if elemClass=="XmlElement" then ( maxElem = XmlElement() maxElem.tagName = elem.name maxElem.textValue = elem.innerText for ai=0 to (elem.Attributes.Count-1) do ( local attrnode = elem.Attributes.itemof ai maxElem.attrs.add attrnode.name attrnode.value ) ) for i=0 to (elem.ChildNodes.Count-1) do ( local child = ParseElementRec (elem.ChildNodes.itemof i) if undefined!=maxElem then ( append maxElem.children child ) ) return maxElem ), -- loads an xml document into memory fn load filename = ( document = dotNetObject "System.Xml.XmlDocument" try( document.Load filename )catch( gRsUlog.LogError ("XML loading failed for file "+filename as string+" due to:"+(getCurrentException())) ) ), -- loads a single element into memory fn loadElement filename element = ( document = dotNetObject "System.Xml.XmlDocument" try( reader = dotNetObject "System.Xml.XmlTextReader" filename )catch( gRsUlog.LogError ("XML loading failed for file "+filename as string+" due to:"+(getCurrentException())) ) if (reader.ReadToFollowing(element)) then ( try( document.Load(reader.ReadSubtree()) )catch( gRsUlog.LogError ("XML loading failed for file "+filename as string+" due to:"+(getCurrentException())) ) ) else ( gRsUlog.LogWarning ("XML reader can't find element '"+element as string+"' in file "+filename as string) ) reader.Close() ), fn ParseIntoMaxscripthierarchy = ( maxXmlObject = ParseElementRec document ) ) fn RsCreateXmlElement name elemattributes xmldoc = ( projelem = xmldoc.createelement(name) for attribute in elemattributes do ( attr = xmldoc.createattribute attribute.name attr.value = attribute.value as string projelem.Attributes.append(attr) ) return projelem ) fn RsGetXmlElement elem elemsearch all:false = ( childelems = elem.childnodes local retArray = #() for i = 0 to ( childelems.Count - 1 ) do ( childelem = childelems.itemof(i) if childelem.name == elemsearch then ( if all then append retArray childelem else return childelem ) ) if all then return retArray else return undefined ) -- End of xml2.ms -- doc = XmlDocument() -- doc.Load "X:/gta5/build/dev/common/data/waterout.xml"