Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
How to add new elements to xml file
Message
From
12/06/2008 23:49:29
 
General information
Forum:
Visual FoxPro
Category:
XML, XSD
Miscellaneous
Thread ID:
01323532
Message ID:
01323694
Views:
14
>Hi Carlos,
>
>Try
>
>loXML = CREATEOBJECT( "MSXML2.DOMDocument" )
>...
>loParentNode = loXML.selectSingleNode("settings/node2/subnode2")
>loElement = loParentNode.appendChild(loXMl.createElement("field4"))
>loElement.nodeTypedValue = "Data224"
>
>

Hi Sergey, thank you for your response. I think I was not clear, but I managed to code a solution. The problem was setting an element value in cases when the node does not exist.

For example, lets say we have an empty XML file like this one:
<?xml version="1.0" encoding="UTF-8"?>
<settings>
</settings>
And I want to save a setting like for example : m.tcSettingName = "settings/node/subnode/element", m.tcSettingValue = "elementvalue"

This is the code I came up with:
Lparameter tcSettingName, tcSettingValue

m.loXml = Createobject("MsXml2.DomDocument")
m.loXml.Async = .F.
m.loXml.Load(This._FileName)

m.lcSettingName = Lower(Chrtran(m.tcSettingName, "\", "/"))

*!* Search for element:
m.loElement = m.loXml.DocumentElement.SelectSingleNode(m.lcSettingName)

If Vartype(m.loElement) = T_OBJECT Then
	*!* Element was found, set text property:
	m.loElement.Text = m.tcSettingValue
Else
	If "/" $ m.lcSettingName Then
		*!* We have a path
		m.lcPath = "/"
		For m.lnx = 1 To Getwordcount(m.lcSettingName, "/")
			m.loNode = m.loXml.DocumentElement.SelectSingleNode(m.lcPath + "/" + Getwordnum(m.lcSettingName, m.lnx, "/"))
			If Vartype(m.loNode) # T_OBJECT Then
				If m.lcPath == "/" Then
					*!* First node, get root node
					m.loNode = m.loXml.DocumentElement
				Else
					*!* Get parent node
					m.loNode = m.loXml.DocumentElement.SelectSingleNode(m.lcPath)
				Endif
				*!* Append node
				m.loNode.appendChild(m.loXml.createNode(NODE_ELEMENT, Getwordnum(m.lcSettingName, m.lnx, "/"),""))
			Endif
			*!* Add next node to path
			m.lcPath = m.lcPath + "/" + Getwordnum(m.lcSettingName, m.lnx, "/")
		Endfor
		*!* By now we are at the element level, set value
		m.loElement = m.loXml.DocumentElement.SelectSingleNode(m.lcSettingName)
		m.loElement.Text = m.tcSettingValue
	Else
		*!* No path, add element to root
		m.loRoot = m.loXml.DocumentElement
		m.loRoot.appendChild(m.loXml.CreateElement(m.lcSettingName))
		m.loRoot.LastChild.Text = m.tcSettingValue
	Endif
Endif

m.loXml.LoadXML(This._FormatXml(m.loXml.XML))
m.loXml.Save(This._FileName)
This seems to work OK, but since this is the first time I have to work with XML, I don´t really know if this is best way/correct way.

By the way, I discovered that the saved XML had no linefeeds! And since the whole idea is to have a settings file that can be easily edited by hand, I had to add
the _FormatXml method:
*!* Adds linefeeds/carriage returns to an xml string
Lparameters tcXml As String

Local ;
	lcXsl As String, ;
	loXml As MsXml2.DomDocument, ;
	loXsl As MsXml2.DomDocument

TEXT To m.lcXsl NoShow
	<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
	<xsl:template match="node() | @*">
	<xsl:copy>
	<xsl:apply-templates select="node() | @*"/>
	</xsl:copy>
	</xsl:template>
	</xsl:stylesheet>
ENDTEXT

m.loXml = Createobject("MsXml2.DomDocument")
m.loXml.LoadXML(m.tcXml)

m.loXsl = Createobject("MsXml2.DomDocument")
m.loXsl.LoadXML(m.lcXsl)

m.lcXml = m.loXml.TransformNode(m.loXsl)

m.loXml = .Null.
m.loXsl = .Null.

*!* Replace encoding added by TransformNode
m.lcXml = Strtran(m.lcXml, 'UTF-16', 'UTF-8')

Return m.lcXml
Again, I don´t know if this is "correct", but it works.

Carlos Alloatti
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform