Files
2025-09-29 00:52:08 +02:00

279 lines
7.3 KiB
Plaintext
Executable File

------------------------------------------------------------------------------
--
-- xml2.ms
-- MaxScript XML Reader/Writer
--
-- David Muir <david.muir@rockstarnorth.com>
-- 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"