Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 275
  • Last Modified:

How to create ONE xml object and add elements to it?

Hi,

I want to create one xml object, so users can add elements/data to it and have it appended as opposed to making a new file each time.

I was going to use <cffile> to write the new form entries to this existing xml file.

How can this be done?

Basically I want to add/append to the xml file each time a user submits entries from a form.

Any thoughts?

-ws
0
Westside2004
Asked:
Westside2004
  • 4
  • 3
  • 2
  • +1
1 Solution
 
pinaldaveCommented:
you can do this...

http://livedocs.macromedia.com/coldfusion/6.1/htmldocs/funca124.htm#wp4279953

<cfset testVar = True>
<cfscript>
   MyDoc = XmlNew();
   MyDoc.xmlRoot = XmlElemNew(MyDoc,"MyRoot");
   if (testVar IS TRUE)
      MyDoc.MyRoot.XmlText = "The value of testVar is True.";
   else
      MyDoc.MyRoot.XmlText = "The value of testVar is False.";
   for (i = 1; i LTE 4; i = i + 1)
      {
      MyDoc.MyRoot.XmlChildren[i] = XmlElemNew(MyDoc,"childNode");
      MyDoc.MyRoot.XmlChildren[i].XmlText = "This is Child node " & i &".";
      }
</cfscript>
<cfdump var=#MyDoc#>

=========================================

http://livedocs.macromedia.com/coldfusion/6.1/htmldocs/funca122.htm#wp4319442

<cfset testVar = True>
<cfscript>
   MyDoc = XmlNew();
   MyDoc.xmlRoot = XmlElemNew(MyDoc,"MyRoot");
   if (testVar IS TRUE)
      MyDoc.MyRoot.XmlText = "The value of testVar is True.";
   else
      MyDoc.MyRoot.XmlText = "The value of testVar is False.";
   for (i = 1; i LTE 4; i = i + 1)
      {
      MyDoc.MyRoot.XmlChildren[i] = XmlElemNew(MyDoc,"childNode");
      MyDoc.MyRoot.XmlChildren[i].XmlText = "This is Child node " & i &".";
      }
</cfscript>
<cfdump var=#MyDoc#>
0
 
Tacobell777Commented:
You can for example use
<cfxml variable="myNewXMLFile">
#oldXMLFile#
#variableContainingXMLToAppend#
</cfxml>

And write variables.myNewXMLFile back to a file.

Make sense?
0
 
Westside2004Author Commented:
So does that overwrite or append?

I am confused on how the #variableContainingXMLToAppend# will add to : #oldXMLFile#

??

-ws
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
Tacobell777Commented:
oldXMLFile is the file you read in (i.e. the file you want to append to) you probably want to read the old file with cffile

variableContainingXMLToAppend is the part you want to append.

I guess you'd want to do something like

<cfxml variable="myNewXMLFile">
<root>
#oldXMLFile#
#variableContainingXMLToAppend#
</root>
</cfxml>

and make sure oldXMLFile is pointing to the elements below the root
0
 
Westside2004Author Commented:
Hi,

For example, lets say I have an xml file called "book.xml"

In it, I have the following code:

<?xml version="1.0" encoding="iso-8859-1"?>
   <book>
        <author>
             <fName>John</fName>
             <lName>Doe</lName>
       </author>
   </book>

So I basically want to be able to add an additional "Author" block to the existing xml file, not the xml opening tag, not add another root element, but just add another element called "author".  This data I want to append is coming from an HTML form.

So if it all worked correctly, I would get:

<?xml version="1.0" encoding="iso-8859-1"?>
   <book>
        <author>
             <fName>John</fName>
             <lName>Doe</lName>
        </author>
        <author>
             <fName>Jane</fName>
             <lName>Smith</lName>
        </author>  
   </book>

I hope that makes my question more clear..

thanks..
-ws
0
 
Tacobell777Commented:
Read xml file into memory ...

create variableContainingXMLToAppend by encoding the form fields into xml

<cfxml variable="myNewXMLFile">
<book>
#oldXMLFile# (only output the author, you might need to loop, and use toString() if you still have an object here)
#variableContainingXMLToAppend# (if you have an xml object here you need to point to the author element only, and use toString())
</book>
</cfxml>

write xml back to file

IF you look at http://www.spike.org.uk/blog/ and scroll down to Copying XML Nodes between documents you'll fin dnaother method of doing it..
0
 
dldeedsCommented:
Here is an other approach. I copied the xml file you gave earlier as an example.

<?xml version="1.0" encoding="iso-8859-1"?>
   <book>
        <author>
             <fName>John</fName>
             <lName>Doe</lName>
       </author>
   </book>
   
I saved it on my local test machine and called it "Author.xml"... and ran the code below. The only thing I did not do was use a real form, I simulated that part, but it should give you an idea on how to add a node to an xml file.

When this example is run, simply hitting refresh will add the same "author" to the file. Be sure you have your checks in place to not allow duplicate submits, or that using the refresh button does not keep adding the same author.


<!--- Simulates names submitted via a form --->
<cfset formFname="FirstName">
<cfset formLname="LastName">

<!--- Read in the "Author.xml" file --->
<cffile action="read" file="D:\CFusionMX\wwwroot\MyTest\XmlTest\Author.xml" variable = "XmlIn" >

<!--- Parse the xml file into a cf xml document object --->
<cfset xmlData=xmlparse('#XmlIn#')>

<!--- Set up some var names to make processing xml roots and children easier --->
<cfset myRoot=xmlData.XmlRoot>
<cfset authorNode=myRoot.xmlChildren>

<!--- Calculate current number of Author nodes and increment by one for new Author index --->
<cfset newAuthor=(ArrayLen(authorNode))+1>

<!--- Set up new Author node using the index var just created --->
<cfset authorNode[newAuthor] = XmlElemNew(xmlData, "author") />

<!--- Set up Xml Children of Fname and Lname for the Author node --->
<cfset authorNode[newAuthor].XmlChildren[1] = XmlElemNew(xmlData, "fname") />
<cfset authorNode[newAuthor].XmlChildren[2] = XmlElemNew(xmlData, "lname") />

<!--- Assign values to the xmlText of the Children XmlElement in your new Author node --->
<cfset authorNode[newAuthor].XmlChildren[1].xmlText = "#formFname#" />
<cfset authorNode[newAuthor].XmlChildren[2].xmlText = "#formLname#" />

<!--- Did a cfdump to see what the object looked like ---
<cfdump var="#xmlData#">

<!--- Convert the new xml document object into a string and write the new Author.xml file to disk --->
<cfset XMLText=ToString(xmlData)>
<cffile action="write" file="D:\CFusionMX\wwwroot\MyTest\XmlTest\Author.xml" output="#XMLText#">

0
 
Westside2004Author Commented:
Hi,

Yes, that worked... thanks a bunch....

The only issue is, its not really an issue, but when I open up the xml file, its all on one line.

Is there a way to keep the formatting so its indented, etc

<?xml version="1.0" encoding="iso-8859-1"?>
   <book>
        <author>
             <fName>John</fName>
             <lName>Doe</lName>
       </author>
   </book>

I get it all on one line... if not, no big deal..... I will live with it, but having it structured in a hierachy is very helpful...

Thanks again!

-ws
0
 
dldeedsCommented:
You could do something like this....

<cfset XMLText=ToString(xmlData)>
<cfset beginAuthor="#chr(9)#<author> #chr(13)#" & "#chr(10)#">
<cfset endAuthor="</author> #chr(13)#" & "#chr(10)#">
<cfset newXmlText1=Replace(XMLText, "<author>", beginAuthor, "ALL")>
<cfset newXmlText2=Replace(newXmlText1, "</author>", endAuthor, "ALL")>
<cffile action="write" file="D:\CFusionMX\wwwroot\MyTest\XmlTest\Author.xml" output="#newXmlText2#">

New var "beginAuthor" adds a TAB in front of the string <author> and a CFLR (carriage return line feed) at the end.
New var "endAuthor" adds a CFLR after the closing </author> tag.
Use the replace function to search the original xmlText string and replace all occurences of <author> with the new var and </author> etc.

I said you could do that...but I wouldn't.

For one thing, everytime you add a new author you will be adding a new tab and crlf to the "author" tags. You could probably do a bunch of coding to get around that, but I am not sure it is worth it.

I don't know what you are using to open the xml file, but most xml editors will open a "long string" xml file with the indenting and line breaks for the various nodes and elements, XmlSpy is pretty good one, and they have a free "home" version that is free, (http://www.altova.com/)

You can also use IE 6+. If you have IE 6 around, open your long string xml file with it. It will be "formatted" properly, (indents and line breaks, etc.). IE even lets you collapse the nodes if you want. Once opened in IE you can copy that format and paste into a text editor like notepad or textpad and it keeps the formatting, you will have to do a replace on the "-" (dashes) that IE puts in for collapsing the nodes, but that is pretty easy to do.

0
 
Westside2004Author Commented:
Hi,

Yah, thanks for that.. seems like a bit of work, maybe for a version 2 or something..

I dont think anyone will open the xml file unless its me.

If it works, then I should be fine without the indenting etc...

Thanks for the help...

-ws
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now