Shawn
|
(KiX Supporter)
|
2005-03-13 02:25 PM
|
|
|
|
|
RFC: ReadXmlString/WriteXmlString
|
|
Realized I probably shoudn't hijack Chris's thread ... in regards to XML and as an offshoot to that thread ...
What I was thinking guys, was to create a matched pair of ReadProfileString/WriteProfileString work-alikes for XML files, to "ease" the interface when one just wants to read/write things like settings, here's a quick prototype of a matched set, plus a snippet of code to demonstrate usage.
break on
$filename = "e:\test.xml"
$xml = LoadXml($filename)
$= WriteXmlValue($xml, "korg/shawn/number", 119)
$= WriteXmlValue($xml, "korg/jose/number", 1772)
$= WriteXmlValue($xml, "korg/jooel/number", 2087)
?"Value=" ReadXmlValue($xml, "korg/jose/number")
SaveXml($xml, $filename)
$xml = 0
exit 1
---
[udf]
Code:
function LoadXml($filename)
dim $, $rootNode
$loadXml = CreateObject("Microsoft.XMLDOM");
if not $loadXml
return
endif
$= $loadXml.Load($filename)
endfunction
function WriteXmlValue($xml, $path, $value)
dim $p, $rootNode, $sectionNode, $parentNode, $childNode
$sectionNode = $xml.SelectSingleNode($path);
if not $sectionNode
$parentNode = $xml
for each $node in split($path,"/")
$p = $p + $node
$sectionNode = $xml.SelectSingleNode($p)
if not $sectionNode
$sectionNode = $xml.CreateElement($node)
$parentNode = $parentNode.AppendChild($sectionNode)
else
$parentNode = $sectionNode
endif
$p = $p + "/"
next
endif
if $sectionNode
$sectionNode.Text = $value
endif
endfunction
function SaveXml($xml, $filename)
$SaveXml = $xml.Save($filename);
endfunction
function ReadXmlValue($xml, $key, optional $defaultValue)
dim $sectionNode
$sectionNode = $xml.SelectSingleNode($key);
if not $sectionNode
$ReadXmlValue = $defaultValue;
else
$ReadXmlValue = $sectionNode.FirstChild.Text;
endif
endfunction
Thoughts ?
|
Shawn
|
(KiX Supporter)
|
2005-03-13 03:53 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Ok, here is an even more powerfull pair of UDF's ... it uses the XML path to read and write, much like a registry key path name. If the path one specifies doesn't exist, the UDF builds the path first, than pokes the value. Here's some examples:
$xmlFile = "e:\t.xml"
$= WriteXmlString($xmlFile, "form1/settings/left", 100)
$= WriteXmlString($xmlFile, "form1/settings/top", 200)
?"value=" ReadXmlString($xmlFile, "form1/settings/top")
[udf]
Code:
function WriteXmlString($filename, $path, $value)
dim $xmlDoc, $rootNode, $sectionNode;
$xmlDoc = CreateObject("Microsoft.XMLDOM");
if not $xmlDoc
return
endif
if not $xmlDoc.Load($filename)
$rootNode = $xmlDoc.createElement("configuration");
$= $xmlDoc.AppendChild($rootNode);
endif
$sectionNode = $xmlDoc.SelectSingleNode("/configuration/" + $path);
if not $sectionNode
$sectionNode = $xmlDoc.documentElement
for each $node in split($path,"/")
$childNode = $xmlDoc.CreateElement($node)
$= $sectionNode.AppendChild($childNode)
$sectionNode = $childNode
next
endif
$sectionNode.Text = $value;
$= $xmlDoc.Save($filename);
return
endfunction
function ReadXmlString($filename, $key, optional $defaultValue)
dim $xmlDoc, $sectionNode
$xmlDoc = CreateObject("Microsoft.XMLDOM")
if not $xmlDoc
return
endif
$= $xmlDoc.Load($filename)
$sectionNode = $xmlDoc.SelectSingleNode("/configuration/" + $key);
if not $sectionNode
$ReadXmlString = $defaultValue;
else
$ReadXmlString = $sectionNode.FirstChild.Text;
endif
endfunction
|
Jose
|
(Seasoned Scripter)
|
2005-03-13 04:28 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Cool Shawn
I was thinking of doing SaveXML() but these two fit better.:).Agree 100% on keeping the writeprofilestring name structure in a very simple way.
It would be also intresting to include Chris idea about the type of XML (;$sFrom: 1 = File; 2 = HTTP; 3 = String) or just do another two like ReadXMLHTTP()-WriteXMLHTTP(). It is a different object thought CreateObject("Microsoft.XMLHTTP")
Have you tested speed on big updates?
|
Shawn
|
(KiX Supporter)
|
2005-03-13 04:33 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jose and I were talking online on MSN, and we thought this strategy would be a more optimized way of writing to xml files, using Chris's LoadXml() idea in concert with these udf's, idea being something like:
$xml = LoadXml("t.xml")
WriteXmlString($xml, "shawn/jose", 100)
WriteXmlString($xml, "shawn/jose2/somesetting/option1", 200)
SaveXml($xml)
$xml = 0
|
Shawn
|
(KiX Supporter)
|
2005-03-13 04:58 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Ok, with apologies to Chris, borrowing his "loadxml" idea, here is a complete set of UDF's for loading/reading/writing/saving from XML files ... looks like this:
break on
$xml = LoadXml("e:\t.xml")
$= WriteXmlString($xml, "shawn/jose", 100) $= WriteXmlString($xml, "shawn/jose/settings/form1/left", 123)
SaveXml($xml, "e:\t.xml")
$xml = 0
exit 1
[udf] Code:
function LoadXml($filename)
dim $, $rootNode
$loadXml = CreateObject("Microsoft.XMLDOM");
if not $loadXml return endif
if not $loadXml.Load($filename)
$rootNode = $loadXml.createElement("root");
if $rootNode
$= $loadXml.AppendChild($rootNode);
endif
endif
endfunction
function SaveXml($xml, $filename)
$SaveXml = $xml.Save($filename);
endfunction
function WriteXmlString($xml, $path, $value)
dim $rootNode, $sectionNode;
$sectionNode = $xml.SelectSingleNode("/root/" + $path);
if not $sectionNode
$sectionNode = $xml.documentElement
for each $node in split($path,"/")
$childNode = $xml.CreateElement($node)
$sectionNode = $sectionNode.AppendChild($childNode)
next
endif
$sectionNode.Text = $value;
return
endfunction
function ReadXmlString($xml, $key, optional $defaultValue)
dim $sectionNode
$sectionNode = $xml.SelectSingleNode("/root/" + $key);
if not $sectionNode $ReadXmlString = $defaultValue; else $ReadXmlString = $sectionNode.FirstChild.Text; endif
endfunction
|
Shawn
|
(KiX Supporter)
|
2005-03-13 06:05 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
hmmm, these UDF's need much more work ... found a few buggy-boos.
|
Jose
|
(Seasoned Scripter)
|
2005-03-13 07:02 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
I was trying to find out why is that when a value is not find the result is a new duplicated branch with new value included wich is wrong.
Here it says here
Quote:
The selectSingleNode method returns a Node object for the first descendant node to match the specified pattern. The one parameter of this method is an XSL pattern query. If no match is made, it returns null. This method is similar to the selectNodes method, but returns only the first node to match the pattern rather than all of them.
So when the there is no match the uds shoudnt do any save, instead should advice about the erro.
Another things to take into account:
- If the file does not exist and you use the write udf, the written file format is all flat (no tab nor enter between tags). I dont know if all interpreters white XML files in flat way or ppl accomadate them by hand.
- If the file is hand formatted after any modification the result are tags separted by tab.
BTW. About the new branch in case is does not exist I have found you can point out where that new branch can be placed, like this
$Elem = $xml.documentElement.firstchild.lastchild
I have dicovered this using $Elem.setAttribute(NAME,VALUE)
-----------------------------------------------------------
Oh I seen now, you have to split the path and see if all tags are present so as to create what is missing after the las known tag.
|
Shawn
|
(KiX Supporter)
|
2005-03-13 10:07 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Updated new set of UDF's in first post ...
|
Allen
|
(KiX Supporter)
|
2005-03-13 10:53 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Shawn, would you mind posting a sample xml file to show what kind of structure you are expecting?
|
Shawn
|
(KiX Supporter)
|
2005-03-13 11:33 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Im not expecting any structure ... the structure is user-defined, for example this sequence of calls:
$= WriteXmlValue($xml, "korg/shawn/number", 119) $= WriteXmlValue($xml, "korg/shawn/lastname", "tassie")
will generate XML that looks like this:
Code:
<korg> <shawn> <number>119</number> <lastname>tassie</lastname> </shawn> </korg>
-Shawn
|
Jose
|
(Seasoned Scripter)
|
2005-03-15 01:44 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Since I am working with Open Office and has plenty of config files stored in xml I have found a very used feature wich is the attrib propertie. This propertie holds values within the XML tag.
Wrote two small UDFs for reading adn writting attributes by its path. WriteXMLattrib() and RearXMLattrib() .
Just run this code wich creates the xml file, if exist c:\temp.
Code:
Break on
$filename = "C:Temp\Shawn.xml"
$xml = LoadXml($filename)
$= WriteXmlValue($xml, "korg/shawn/City", "Toronto")
$= WriteXmlValue($xml, "korg/shawn/Country", "Canada")
$= WriteXmlValue($xml, "korg/shawn/Registred", "17/08/1999")
$= WriteXMLattrib($xml, "korg/shawn", "Id", "5200")
$= WriteXMLattrib($xml, "korg/shawn", "Age", "25")
SaveXml($xml, $filename)
$xml = 0
Open the file and take a look at the values Id and Age, they are attributes of Shawn.
Run this script to see those values.
Code:
Break on
$filename = "C:Temp\Shawn.xml"
$xml = LoadXml($filename)
$ShawnCity = ReadXmlValue($xml, "korg/shawn/City")
$ShawnCountry = ReadXmlValue($xml, "korg/shawn/Country")
$ShawnRegistred = ReadXmlValue($xml, "korg/shawn/Registred")
$ShawnId = RearXMLattrib($xml, "korg/shawn", "Id")
$ShawnAge = RearXMLattrib($xml, "korg/shawn", "Age")
? "Shawn Id Attribute= "+$ShawnId
? "Shawn Age Attribute= "+$ShawnAge
? "Shawn City Value= "+$ShawnCity
? "Shawn Country Value= "+$ShawnCountry
? "Shawn Registred Value= "+$ShawnRegistred
$xml = 0
Sleep 5
Functions:
Code:
Function LoadXml($filename)
Dim $, $rootNode
$loadXml = CreateObject("Microsoft.XMLDOM");
If NOT $loadXml
Return
EndIf
$= $loadXml.Load($filename)
EndFunction
Function WriteXmlValue($xml, $path, $value)
Dim $p, $rootNode, $sectionNode, $parentNode, $childNode
$sectionNode = $xml.SelectSingleNode($path);
If NOT $sectionNode
$parentNode = $xml
For Each $node In Split($path,"/")
$p = $p + $node
$sectionNode = $xml.SelectSingleNode($p)
If NOT $sectionNode
$sectionNode = $xml.CreateElement($node)
$parentNode = $parentNode.AppendChild($sectionNode)
Else
$parentNode = $sectionNode
EndIf
$p = $p + "/"
Next
EndIf
If $sectionNode
$sectionNode.Text = $value
EndIf
EndFunction
Function SaveXml($xml, $filename)
$SaveXml = $xml.Save($filename);
EndFunction
Function ReadXmlValue($xml, $key, optional $defaultValue)
Dim $sectionNode
$sectionNode = $xml.SelectSingleNode($key);
If NOT $sectionNode
$ReadXmlValue = $defaultValue;
Else
$ReadXmlValue = $sectionNode.FirstChild.Text;
EndIf
EndFunction
Function WriteXMLattrib($xml, $Path, $Attr, $Value)
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
$eu = $AttrTag.SetAttribute($Attr,$Value);
EndFunction
Function RearXMLattrib($xml, $Path, $Attr)
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrName = $SelectionTag.item(0)
$RearXMLattrib =$AttrName.getAttribute($Attr)
EndFunction
I think we are getting to an intresting point, this is very fast and looks good to me.
BTW: I cannot paste XML code cause we "Newbyes" dont have ATTRIBUTES !!! for that sort of pleasures.
|
Lonkero
|
(KiX Master Guru)
|
2005-03-15 08:40 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
it has nothing to do with newbye stuff.
|
Jose
|
(Seasoned Scripter)
|
2005-03-15 08:53 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Yeah I know I was kidding. Do you know how to disable html Jooel?
Try to use a normal user (non-mod) and you will see what I mean.
|
Lonkero
|
(KiX Master Guru)
|
2005-03-15 09:12 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
works just fine...
|
Jose
|
(Seasoned Scripter)
|
2005-03-15 09:16 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Well this yould be the xml result file for last script. I can use it Jooel thanks man!.
Code:
- <korg>
- <shawn Id="5200" Age="25">
<City>Toronto</City>
<Country>Canada</Country>
<Registred>17/08/1999</Registred>
</shawn>
</korg>
|
jtokach
|
(Seasoned Scripter)
|
2005-03-15 06:38 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Is there a reason these aren't in the UDF forum?
|
Shawn
|
(KiX Supporter)
|
2005-03-15 06:40 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Because they're "evolving" ... ;0)
|
jtokach
|
(Seasoned Scripter)
|
2005-03-15 07:25 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Ah... (Sorry, didn't read the post dates!) The dog poo on my lawn is evolving too. =)
XML is the answer to all of my problems. Even dog poo.
Code:
<labrador>
<dogchow>
<poo>
<fluffydog>Wag tail</fluffydog>
<neighbors>Pinch nose</neighbors>
<jim>Ignore responsibility</jim>
<wife>Clean poo</wife>
</poo>
</dogchow>
</labrador>
|
Shawn
|
(KiX Supporter)
|
2005-03-15 07:49 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Les, you paying attention ? (Les just got a pup fyi)
|
jtokach
|
(Seasoned Scripter)
|
2005-03-15 07:57 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Congratulations Les!
Please note that the above does not apply to diapers... Replacing the <fluffydog> section with <baby>Crying</baby> blows the whole plan clear out of the water. As the matter of fact, it's untested, but implementing <jim>ignore responsibilities</jim> any where in the dirty diaper routine will most likely throw an exception at <wife>
|
jtokach
|
(Seasoned Scripter)
|
2005-03-15 11:18 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
I'm playing around with this a bit, but Kix doesn't seem to handle this object model correctly?
Code:
$objXMLDoc = CreateObject("Microsoft.XMLDOM") $objXMLDoc.async = False $=$objXMLDoc.load("C:\my.xml")
$j = " version = " + chr(34) +"1.0" + chr(34)
Dim $objNewPI, $currNode $objNewPI = $objXMLDoc.createProcessingInstruction("xml", $j) ? "EE0:"@error ? "ES0:"@Serror $d = $objXMLDoc.firstChild ? "EE1:"@error ? "ES1:"@Serror $= $objXMLDoc.insertBefore ($objNewPI,$d) $= $objXMLDoc.save("C:\my.xml")
Beyond that, it seems as though preservewhitespace is completely ignored. With the code you guys have so far, the indenting should be there...
|
Les
|
(KiX Master)
|
2005-03-15 11:50 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
$objXMLDoc.async = False
KiX does not have a keyword named "False"
|
jtokach
|
(Seasoned Scripter)
|
2005-03-16 12:05 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Umm... Code:
$objXMLDoc = CreateObject("Microsoft.XMLDOM") ? "Before "$objXMLDoc.async $objXMLDoc.async = False ? "After "$objXMLDoc.async
|
Jose
|
(Seasoned Scripter)
|
2005-03-16 12:15 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Async
Code:
$objNewPI = $objXMLDoc.createProcessingInstruction("xml", $j) Havent seen function within the XMLDOM object.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-16 12:30 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
It adds that header line. Not of any value that I can see for our immediate needs. Got it working, but it's still freakin wierd. I puzzled as to the formatting???
Code:
function LoadXml($filename) dim $, $rootNode, $objNewPI, $strType
$loadXml = CreateObject("Microsoft.XMLDOM"); $loadXml.async = False $loadXml.preserverwhitespace = True
if not $loadXml return endif
$ = $loadXml.Load($filename) $strType = " version = " + chr(34) + "1.0" + chr(34) $objNewPI = $loadXml.createProcessingInstruction("xml", $strType) $ = $loadXml.insertBefore ($objNewPI,$objXMLDoc.firstChild) endfunction
|
Jose
|
(Seasoned Scripter)
|
2005-03-16 01:59 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
I see your point Jim, sorry I didnt undertand.
Quote:
I'm playing around with this a bit, but Kix doesn't seem to handle this object model correctly?
You are right.
The header idea is very good but does not work as it should. Me cannot make it work either.
Code:
$objNewPI = $loadXml.createProcessingInstruction("xml", $strType)
I get @error=2147352570
Code:
$ = $loadXml.insertBefore ($objNewPI,$objXMLDoc.firstChild)
I get @error=6
I have tryed with the XMLDOM error method ($objXMLDoc.parseError) but nothing. All DOM errors=0.
I think it is compulsory for these udf´s to include this feature and we should find out how. VBScrit source.
Any ideas guys? Can anyone else give a try?
|
Jose
|
(Seasoned Scripter)
|
2005-03-16 10:58 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Talking to Jooel he suggeted to use the old friend writeline() to write the header. I am more the opinion of using the same object developed for that purpose but this particular code seems to be stucked using kix.
Thoughts?
|
jtokach
|
(Seasoned Scripter)
|
2005-03-16 05:54 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jose, that header code works for me, not sure why your seeing those errors.
Regarding writeline(), I'm half tempted to say screw xmldom object model and do everything with arrays, readline and writeline...
Regarding formatting, the single line seems to be the only output xmldom is capable of producing. Formatting is a separate process: Somewhat automated way of formatting .xml
It's in VB, but at a glance, it looks like it can be converted.
|
Shawn
|
(KiX Supporter)
|
2005-03-16 07:24 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jim, not too sure I would dismiss XML so quickly. Personally, I'm hoping to get some screaming performance gains versus the builtin WriteLine and WriteProfileString functions. Although I have no data to back this up, the Kixtart builtins are slow as hell (especially writing stuff). Think some benchmarking is in order.
The other thing ... wish I could figure-out a way to get the output XML properly formatted. When notepadding the result, all the data is scrunched into one long line. Must be a way to introduce some formatting in there.
|
Lonkero
|
(KiX Master Guru)
|
2005-03-16 07:52 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
so, you say com stuff is faster than writeline? uuh...
and who did say anything about dismissing xml? xml is lot more than the lame com stuff used in this thread.
|
Jose
|
(Seasoned Scripter)
|
2005-03-16 08:38 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Quote:
xml is lot more than the lame com stuff used in this thread.
I dont like this.
|
Lonkero
|
(KiX Master Guru)
|
2005-03-16 08:45 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
I knew you wouldn't like it. you like the com-object. but finally you have to admit that xml is just pure text and nothing much more.
|
Jose
|
(Seasoned Scripter)
|
2005-03-16 08:55 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Com or text is the same as you said, and there sure are thrid party ways of doing it too.
What I dont like is you making that opinion about something I had involved in.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-16 10:37 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Quote:
Jim, not too sure I would dismiss XML so quickly. Personally, I'm hoping to get some screaming performance gains versus the builtin WriteLine and WriteProfileString functions. Although I have no data to back this up, the Kixtart builtins are slow as hell (especially writing stuff). Think some benchmarking is in order.
If it wasn't so complicated, I wouldn't mind so much, but it sucks and something seems to be unpredictable. Again, I renew my request for builtin xml support in Kix. =)
Quote:
The other thing ... wish I could figure-out a way to get the output XML properly formatted. When notepadding the result, all the data is scrunched into one long line. Must be a way to introduce some formatting in there.
I posted this in the previous post. It's written in VB. It is terribly inconvenient but not sure it's that big of an issue. We'll need to stick to IE until someone can translate that VB code. I started, but I can't find a suitable replacement for the TypeOf statements, yet...
|
jtokach
|
(Seasoned Scripter)
|
2005-03-17 06:09 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Hail to the King Baby!
-Formatting hooked up! (Needed to apply XSL)
-Updated all code for Option Explicit
Code:
break on
$nul=SetOption("ASCII","On")
$nul=SetOption("Explicit","On")
Dim $filename,$xml,$
$filename = "C:\HailToTheKingBaby.xml"
$xml = LoadXml($filename)
$= WriteXmlValue($xml, "korg/shawn/number", 119)
$= WriteXmlValue($xml, "korg/jose/number", 1772)
$= WriteXmlValue($xml, "korg/jooel/number", 2087)
?"Value=" ReadXmlValue($xml, "korg/jose/number")
SaveXml($xml, $filename)
$xml = 0
exit 1
function LoadXml($filename)
dim $, $rootNode, $objNewPI, $strType
$loadXml = CreateObject("Microsoft.XMLDOM")
$loadXml.async = False
$loadXml.preserverwhitespace = True
if not $loadXml
return
endif
$ = $loadXml.Load($filename)
endfunction
Function FormatXML($objXMLDOM)
Dim $,$strXSL,$objXSL
;Create and Load XSL
; <?xml version="1.0" encoding="UTF-8"?>
; <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
; <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
; <xsl:template match="/ | @* | node()">
; <xsl:copy>
; <xsl:apply-templates select="@* | node()" />
; </xsl:copy>
; </xsl:template>
; </xsl:stylesheet>
$strXSL = "<?xml version=" + chr(34) + "1.0" + chr(34) + " encoding=" +
chr(34) + "UTF-8" + chr(34) + "?>" + @CRLF
$strXSL = $strXSL + "<xsl:stylesheet version=" + chr(34) + "1.0" + chr(34) +
" xmlns:xsl=" + chr(34) + "http://www.w3.org/1999/XSL/Transform" +
chr(34) + ">" + @CRLF
$strXSL = $strXSL + "<xsl:output method=" + chr(34) + "xml" + chr(34) +
" version=" + chr(34) + "1.0" + chr(34) + " encoding=" + chr(34) +
"UTF-8" + chr(34) + " indent=" + chr(34) + "yes" + chr(34) + "/>" + @CRLF
$strXSL = $strXSL + "<xsl:template match=" + chr(34) + "/ | @@* | node()" +
chr(34) + ">" + @CRLF
$strXSL = $strXSL + "<xsl:copy>"+ @CRLF
$strXSL = $strXSL + "<xsl:apply-templates select=" + chr(34) +
"@@* | node()" + chr(34) + " />"+ @CRLF
$strXSL = $strXSL + "</xsl:copy>"+ @CRLF
$strXSL = $strXSL + "</xsl:template>"+ @CRLF
$strXSL = $strXSL + "</xsl:stylesheet>"
;? "XLM Stylesheet: " + @CRLF + $strXSL
$objXSL = CreateObject("Microsoft.XMLDOM")
$objXSL.async = false
$=$objXSL.loadXML($strXSL)
;Transform file
$objXMLDOM.TransformNodeToObject ($objXSL, $objXMLDOM)
$formatXML = $objXMLDOM
EndFunction
function WriteXmlValue($xml, $path, $value)
dim $p, $rootNode, $sectionNode, $parentNode, $childNode,$node
$sectionNode = $xml.SelectSingleNode($path);
if not $sectionNode
$parentNode = $xml
for each $node in split($path,"/")
$p = $p + $node
$sectionNode = $xml.SelectSingleNode($p)
if not $sectionNode
$sectionNode = $xml.CreateElement($node)
$parentNode = $parentNode.AppendChild($sectionNode)
else
$parentNode = $sectionNode
endif
$p = $p + "/"
next
endif
if $sectionNode
$sectionNode.Text = $value
endif
endfunction
function SaveXml($xml, $filename)
$xml = formatXML($xml)
$SaveXml = $xml.Save($filename)
endfunction
function ReadXmlValue($xml, $key, optional $defaultValue)
dim $sectionNode
$sectionNode = $xml.SelectSingleNode($key);
if not $sectionNode
$ReadXmlValue = $defaultValue;
else
$ReadXmlValue = $sectionNode.FirstChild.Text;
endif
endfunction
|
jtokach
|
(Seasoned Scripter)
|
2005-03-17 06:57 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jose, I updated your attrib UDF's. Also renamed the one from Rear to Read (I assumed that was a typo.)
Code:
Function WriteXMLattrib($xml, $Path, $Attr, $Value)
Dim $SelectionTag,$AttrTag,$,$eu
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
If @Serror = "Member not found."
$= WriteXmlValue($xml, $path, "")
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
EndIf
$eu = $AttrTag.SetAttribute($Attr,$Value)
EndFunction
Function ReadXMLattrib($xml, $Path, $Attr)
Dim $SelectionTag,$AttrName
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrName = $SelectionTag.item(0)
If @Serror = "Member not found."
$ReadXMLattrib = ""
Exit @Error
Else
$ReadXMLattrib =$AttrName.getAttribute($Attr)
EndIf
EndFunction
|
NTDOC
|
(KiX Master)
|
2005-03-17 07:07 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
FYI - Link to XSL that Jim refers to.
http://www.w3.org/Style/XSL/
Learning link http://www.w3schools.com/xsl/
XSL Frequently Asked Questions http://www.dpawson.co.uk/xsl/xslfaq.html
|
Jose
|
(Seasoned Scripter)
|
2005-03-17 08:20 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jim you have done a fantastic job man!!
LOL Rear. Havent realized . Silly me
ReadXMLattrib() looks much better.
|
Jose
|
(Seasoned Scripter)
|
2005-03-17 09:22 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jim: I have changed two things in the attrib functions. - I have spanish languaje so changed to @error in case path not exist. - took the $eu off and replaced with $Write
Code:
Function WriteXMLattrib($xml, $Path, $Attr, $Value)
Dim $SelectionTag,$AttrTag,$,$Write
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0) If @ERROR = "-2147352573"
$= WriteXmlValue($xml, $path, "")
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
EndIf
$write = $AttrTag.SetAttribute($Attr,$Value)
EndFunction
Function ReadXMLattrib($xml, $Path, $Attr)
Dim $SelectionTag,$AttrName
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrName = $SelectionTag.item(0)
If @ERROR = "-2147352573"
$ReadXMLattrib = ""
Exit @Error
Else
$ReadXMLattrib =$AttrName.getAttribute($Attr)
EndIf
EndFunction
|
jtokach
|
(Seasoned Scripter)
|
2005-03-17 10:35 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jose,
Sorry for being so ignorant!!! It didn't even occur to me that @serror would be different b/w languages.
I think we need some more though as to how this is going to progress. I'm thinking we need and EnumXML().
Also, not sure that LoadXML and SaveXML are the best method of approaching this. Shouldn't these be built right into all of the Write and Read functions; like ReadProfileString and WriteProfileString? Granted that there would be much more overhead, but much simpler to write code with. I guess that's where you'd lose your performance gain, eh Shawn? But, at least I'd be able to perform a Read operation right after write operation because the data is immediately commited to disk.
Current:
Code:
LoadXML()
Get data...
WriteXMLValue()
Get more data...
WriteXMLValue()
SaveXML()
and
LoadXML()
ReadXMLValue()
ReadXMLValue()
SaveXML()
Jim Preferred:
Code:
WriteXMLValue()
ReadXMLValue()
WriteXMLValue()
ReadXMLValue()
ReadXMLValue()
WriteXMLValue()
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 01:10 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Regarding EnumXML(), here's where I'm at:
Code:
Function EnumXML($xml) Dim $i,$a,$NodeList $NodeList = $xml.getElementsByTagName("*") For Each $i In $NodeList ? "Element " +$i.tagName ;? "attributes: " $i.attributes ;? "baseName: " $i.baseName ;? "childNodes: " $i.childNodes ;? "dataType: " $i.dataType ;? "definition: " $i.definition ? "firstChild: " $i.firstChild.nodeName ? "lastChild: " $i.lastChild.nodeName ;? "namespaceURI: " $i.namespaceURI ? "nextSibling: " $i.nextSibling.nodeName ;? "nodeName: " $i.nodeName ;? "nodeType: " $i.nodeType ;? "nodeTypeString: " $i.nodeTypeString ;? "nodeValue: " $i.nodeValue ;? "ownerDocument: " $i.ownerDocument ? "parentNode: " $i.parentNode.nodeName ;? "parsed: " $i.parsed ;? "prefix: " $i.prefix ;? "previousSibling: " $i.previousSibling.nodeName ;? "specified: " $i.specified ;? "tagName: " $i.tagName ;? "text: " $i.text ;? "xml: " $i.xml ?? Next ;? "root: "$xml.documentElement.NodeName
;$a = xml_doc.getElementsByTagName("*") ;for each $i in $a ; item($i).text ; next ; for each $i in $xml.documentElement.childNodes ; Dim $k,$m ; ? "lvl1: " $xml.documentElement.NodeName + "/" + $i.nodeName ; ;GetXMLChildElements($xml,$xml.documentElement.NodeName + "/" + $i.nodeName) ; next EndFunction
|
Shawn
|
(KiX Supporter)
|
2005-03-18 01:25 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
We did originally perform the Load and Save in WriteXMLValue, loading and saving on every write, then just decided that that wasn't very efficient, so removed - didn't perform any bench-marking or anything, might not be too bad. Doing that load and save certainly makes the whole thing easier to use - for sure.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 05:15 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
EDIT1: Renamed some stuff and added some stuff.
EDIT2: Added Remove* functions (Jose suggestion)
Renamed functions from *Attribute to *Attr
Shawn, if there's sufficient reason to, we can 'overload' these functions by allowing the source argument to be either a path\filename, an XMLDOM object, or an XML string. This raises the complexity of the functions, but also addresses performance and increases usability.
All, I'm envisioning these functions as a cross between the _profilestring functions and the registry functions. Kinda mimics real life as XML seems to be a cross between INI and a hierarchal db like the REG. Here's how I see it, please comment:
Core functions (We have a solid base on most of this already)
Code:
LoadXML() - Load an existing .XML file, instantiate XMLDOM object for use regardless of file existance.
SaveXML() - Saves an XMLDOM object
FormatXML() - Formats the output style of an XMLDOM object to the standard
EnumXMLElement() - Enums child elements of a given element
EnumXMLAttr() - Enums all attributes of an element
CreateXMLElement() - Creates an empty element pair
RemoveXMLElement() - Deletes an XML element (Recursively?)
WriteXMLValue() - Writes a value to an XML element
ReadXMLValue() - Reads the value of an XML element
WriteXMLAttr() - Writes an attribute to an XML element
ReadXMLAttr() - Read a specific attribute of an XML element
RemoveXMLAttr() - Deletes an XML element attribut
Secondary functions
Code:
ApplyXSL() - Applies an XSL template. (Much potential here for an expanded set, see
http://www.devguru.com/Technologies/xslt/quickref/xslt_index.html
or NTDOC's post above.
FilterXML() - Apply a filter to an XMLDOM object. (Search the db. XSL related.)
|
Shawn
|
(KiX Supporter)
|
2005-03-18 05:28 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
I'm cool with overloading, good idea, so the write overloads would look like:
WriteXmlValue(string, string, variant)
-and-
WriteXmlValue(object, string, variant)
Where if the first parm is a string, it means its a filename, and if its an object, means its a xml object. ja ?
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 05:40 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Bingo. Even more than that though.
WriteXmlValue(string, string, variant) WriteXmlValue(object, string, variant)
and
WriteXmlValue(xmlstring, string, variant)
Where if instr(xmlstring,"<") Not a filename, but an XML string of elements. So you could build your XML file in a string and then do a $=$objXML.loadXML($strXML) (note the loadXML method instead of .load)
I really haven't thought out what this would buy us as brainstorming doesn't lend well to rational thought. But, I think later it may handy when dealing with creating XSL on the fly or creating new .XML files from portions of existing XML.
I forgot to add WriteXmlValue() the previous list... Done.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 05:48 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
And one more request... (don't crucify me) but can we possibly not use Optional args? I plan on rewriting these in .VBS and it just makes life easier.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 06:55 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString - division of labor
|
|
I'm going to start working on EnumXMLElement() and EnumXMLAttribute(). If someone is writing code on this, please let us know what you're doing.
Both of these will return an array on success, or a null string otherwise (with errorlevel for further definition)
|
Jose
|
(Seasoned Scripter)
|
2005-03-18 07:02 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Not me Jim I think we hould also add these two.
RemoveXMLElement()
RemoveXMLattr()
I have tryed the second one. Coudnt afford using optional arg Jim .
Code:
Function RemoveXMLattr($xml, $Path, $attr, optional $id)
Dim $SelectionTag,$AttrTag,$erase
$SelectionTag = $xml.getElementsByTagName($Path)
If $id=""
$id=0
EndIf
$AttrTag = $SelectionTag.item($id)
$erase = $AttrTag.removeAttribute($attr)
EndFunction
Posting sample.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 07:14 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Good call Jose, I'll add them to that list.
Yeah, sometimes you can't get around using optionals. In that case, with .VBS, I force sending all arguments where optionals contain NULL.
|
Jose
|
(Seasoned Scripter)
|
2005-03-18 07:24 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Te optional comes cause you could have a sample like this: Code:
<?xml version="1.0" encoding="UTF-8" ?> <Albums> <Album ref="CD142" category="Folk"> <title>Boil The Breakfast Early</title> <artist>The Chieftains</artist> </Album> <Album ref="CD720" category="Pop"> <title>Come On Over</title> <artist>Shania Twain</artist> </Album> <Album ref="CD024" category="Country"> <title>Red Dirt Girl</title> <artist>Emmylou Harris</artist> </Album> </Albums>
Code:
$=RemoveXMLattr($xml, "Albums/Album", "category", 0)
In wich case you have to indicate the att id to erase it. 0 should remove category="Folk" in this case. Maybe would be better to search for the attr, get the id and then arease it if you dont now it.
|
Allen
|
(KiX Supporter)
|
2005-03-18 07:39 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Code:
<Album ref="CD142" category="Folk"> <title>Boil The Breakfast Early</title> <artist>The Chieftains</artist> </Album>
ahh just what I was wondering about earlier... Shawn, Jose's code above is exactly where I was going with my earlier question about the XML format you are expecting. In this example there are values defined within the Album (ref="CD142"), and then child attributes like title and artitist.
I'll be the first one to admit, I don't know a whole lot about XML, but would it be easiest to say the format of the XML is expected to be only one way or another, or are the UDFs already taking in consideration the altering data formats?
|
Les
|
(KiX Master)
|
2005-03-18 08:00 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Pardon me for jumping in this late in the game. I thought I read early on that the objective was to "emulate" the INI file handling like WriteProfileString() does. Now I see it is more like WriteLine() whereby the file needs to be opened, read, written, closed, etc., and now something to remove elements? I know I did not read every word in this thread but I don't recall a change of objective stated anywhere, just creep.
|
Jose
|
(Seasoned Scripter)
|
2005-03-18 08:00 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Allen:
The thing about XML is that you are free to format it as you wish. There is not defined structure to use it as an mdb database.
You can have either different child names like this, used in a straight way as ini.
Code:
- <korg>
- <shawn>
<number>119</number>
</shawn>
- <jose>
<number>1772</number>
</jose>
- <jooel>
<number>2087</number>
</jooel>
</korg>
Or you can have same childs widh are defined by different attributes. Like this.
Code:
- <Albums>
- <Album ref="CD142" category="Folk">
<title>Boil The Breakfast Early</title>
<artist>The Chieftains</artist>
</Album>
- <Album ref="CD720" category="Pop">
<title>Come On Over</title>
<artist>Shania Twain</artist>
</Album>
- <Album ref="CD024" category="Country">
<title>Red Dirt Girl</title>
<artist>Emmylou Harris</artist>
</Album>
</Albums>
In wich case ref="CD142" is an attribute for that particular album.
This is what I have seen by now about XLM I think none of us is expert we are just getting into knowing it.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 08:01 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Allen,
This is why I'm modeling after INI+REG. You can combine both styles, and most programmer do. So like the REG functions: EnumKey, EnumValues, do something. Given the current setup: EnumXMLElements, ReadXMLValue, EnumXMLAttr.
The extra step is required b/c XML is basically a combo of INI and hierarcal REG.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 08:18 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Les, the *ProfileString do the same thing, although Kix does the work of open and close behind the scenes. Since we can't operate at that level, we have no choice but to Open, Read/Write, Close somewhere, either internal to the function or external to it.
I asked Shawn, in a previous post, why LoadXML and SaveXML were seperated, and he stated for effeciency. Our collective agreement has been to overload the functions so that both methods (writeline type and *profilestring) are available.
|
Jose
|
(Seasoned Scripter)
|
2005-03-18 08:31 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
And.....I dont think that any other languajes that invoke XMLDOM are using it other that we are trying to use now, its XMLDOM way.
|
Jose
|
(Seasoned Scripter)
|
2005-03-18 08:39 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jim?
Quote:
RemoveXMLElement() - Deletes an XML element (Recursively?)
What do you mean by Recursively? sorry if I dont get it.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 08:47 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Jose, not sure if the delete methods of XMLDOM will allow you to delete an element that has children. Haven't done any research into it yet. I think it does which would make it recursive, in a sense.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 08:52 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Here's all of what we have so far. Some functions have been renamed from their original.
LoadXML() - Load an existing .XML file, instantiate XMLDOM object for use regardless of file existance.
SaveXML() - Saves an XMLDOM object
FormatXML() - Formats the output style of an XMLDOM object to the standard
EnumXMLElement() - Enums child elements of a given element
EnumXMLAttr() - Enums all attributes of an element
CreateXMLElement() - Creates an empty element pair
RemoveXMLElement() - Deletes an XML element (Recursively?)
WriteXMLValue() - Writes a value to an XML element
ReadXMLValue() - Reads the value of an XML element
WriteXMLAttr() - Writes an attribute to an XML element
ReadXMLAttr() - Read a specific attribute of an XML element
RemoveXMLAttr() - Deletes an XML element attribut
Secondary functions
ApplyXSL() - Applies an XSL template. (Much potential here for an expanded set, see
http://www.devguru.com/Technologies/xslt/quickref/xslt_index.html
or NTDOC's post above.
FilterXML() - Apply a filter to an XMLDOM object. (Search the db. XSL related.)
Code:
; CreateXMLElement() - Creates an empty element pair
Function CreateXMLElement()
EndFunction
; EnumXMLAttr() - Enums all attributes of an element
Function EnumXMLAttr()
EndFunction
; EnumXMLElement() - Enums child elements of a given element
Function EnumXMLElement()
EndFunction
;FormatXML() - Formats the output style of an XMLDOM object to the standard
Function FormatXML($objXMLDOM)
Dim $,$strXSL,$objXSL
;Create and Load XSL
; <?xml version="1.0" encoding="UTF-8"?>
; <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
; <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
; <xsl:template match="/ | @* | node()">
; <xsl:copy>
; <xsl:apply-templates select="@* | node()" />
; </xsl:copy>
; </xsl:template>
; </xsl:stylesheet>
$strXSL = "<?xml version=" + chr(34) + "1.0" + chr(34) + " encoding=" +
chr(34) + "UTF-8" + chr(34) + "?>" + @CRLF
$strXSL = $strXSL + "<xsl:stylesheet version=" + chr(34) + "1.0" + chr(34) +
" xmlns:xsl=" + chr(34) + "http://www.w3.org/1999/XSL/Transform" +
chr(34) + ">" + @CRLF
$strXSL = $strXSL + "<xsl:output method=" + chr(34) + "xml" + chr(34) +
" version=" + chr(34) + "1.0" + chr(34) + " encoding=" + chr(34) +
"UTF-8" + chr(34) + " indent=" + chr(34) + "yes" + chr(34) + "/>" + @CRLF
$strXSL = $strXSL + "<xsl:template match=" + chr(34) + "/ | @@* | node()" +
chr(34) + ">" + @CRLF
$strXSL = $strXSL + "<xsl:copy>"+ @CRLF
$strXSL = $strXSL + "<xsl:apply-templates select=" + chr(34) +
"@@* | node()" + chr(34) + " />"+ @CRLF
$strXSL = $strXSL + "</xsl:copy>"+ @CRLF
$strXSL = $strXSL + "</xsl:template>"+ @CRLF
$strXSL = $strXSL + "</xsl:stylesheet>"
;? "XLM Stylesheet: " + @CRLF + $strXSL
$objXSL = CreateObject("Microsoft.XMLDOM")
$objXSL.async = false
$=$objXSL.loadXML($strXSL)
;Transform file
$objXMLDOM.TransformNodeToObject ($objXSL, $objXMLDOM)
$formatXML = $objXMLDOM
EndFunction
;LoadXML() - Load an existing .XML file, instantiate XMLDOM object for use
;regardless of file existance.
Function LoadXML($filename)
dim $, $rootNode, $objNewPI, $strType
$loadXml = CreateObject("Microsoft.XMLDOM")
$loadXml.async = False
$loadXml.preserverwhitespace = True
if not $loadXml
return
endif
$ = $loadXml.Load($filename)
EndFunction
; ReadXMLAttr() - Read a specific attribute of an XML element
Function ReadXMLAttr($xml, $Path, $Attr)
Dim $SelectionTag,$AttrName
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrName = $SelectionTag.item(0)
If @Serror = "Member not found."
$ReadXMLAttr = ""
Exit @Error
Else
$ReadXMLAttr =$AttrName.getAttribute($Attr)
EndIf
EndFunction
;ReadXMLElement() - Reads the value of an XML element
Function ReadXMLValue($xml, $key, optional $defaultValue)
Dim $sectionNode
$sectionNode = $xml.SelectSingleNode($key)
If not $sectionNode
$ReadXmlValue = $defaultValue
Else
$ReadXmlValue = $sectionNode.FirstChild.Text
EndIf
EndFunction
; RemoveXMLAttr() - Deletes an XML element attribute
Function RemoveXMLAttr($xml, $Path, $attr, optional $id)
Dim $SelectionTag,$AttrTag,$erase
$SelectionTag = $xml.getElementsByTagName($Path)
If $id=""
$id=0
EndIf
$AttrTag = $SelectionTag.item($id)
$erase = $AttrTag.removeAttribute($attr)
EndFunction
; RemoveXMLElement() - Deletes an XML element (Recursively?)
Function RemoveXMLElement()
EndFunction
;SaveXML() - Saves an XMLDOM object to a file
; Requires: FormatXML()
Function SaveXML($xml, $filename)
$xml = FormatXML($xml)
$SaveXml = $xml.Save($filename)
EndFunction
; WriteXMLAttr() - Writes an attribute to an XML element
Function WriteXMLAttr($xml, $Path, $Attr, $Value)
Dim $SelectionTag,$AttrTag,$,$eu
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
If @Serror = "Member not found."
$ = WriteXmlValue($xml, $path, "")
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
EndIf
$eu = $AttrTag.SetAttribute($Attr,$Value)
EndFunction
; WriteXMLValue() - Writes a value to an XML element
Function WriteXMLValue($xml, $path, $value)
dim $p, $rootNode, $sectionNode, $parentNode, $childNode,$node
$sectionNode = $xml.SelectSingleNode($path);
if not $sectionNode
$parentNode = $xml
for each $node in split($path,"/")
$p = $p + $node
$sectionNode = $xml.SelectSingleNode($p)
if not $sectionNode
$sectionNode = $xml.CreateElement($node)
$parentNode = $parentNode.AppendChild($sectionNode)
else
$parentNode = $sectionNode
endif
$p = $p + "/"
next
endif
if $sectionNode
$sectionNode.Text = $value
endif
endfunction
; ******************************************************************************
; ApplyXSL() - Applies an XSL template. (Much potential here for an expanded
; set, see http://www.devguru.com/Technologies/xslt/quickref/xslt_index.html
Function ApplyXSL()
EndFunction
; FilterXML() - Apply a filter to an XMLDOM object. (Search the db. XSL related.)
Function FilterXML()
EndFunction
|
Jose
|
(Seasoned Scripter)
|
2005-03-18 09:06 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
This is quite an achievement man!!
From nothing we have plenty of stuff now.
About the delete method I think it should delete both element and children I will se if I can get along with it, if not I shout it out.
Ahh...remember to update Write-ReadXMLAttr() for the languaje issue. Remember "Member not found."?
|
jtokach
|
(Seasoned Scripter)
|
2005-03-18 09:27 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Damn. I thought I did...
Here's the Overload code implemented into a function. Works great. I guess I'll retrofit all of the function to use this before I tackle the other funcs. I'll update the post aobve with the language changes and this. Code:
; WriteXMLValue() - Writes a value to an XML element Function WriteXMLValue($source, $path, $value) dim $, $p, $rootNode, $sectionNode, $parentNode, $childNode, $node, $xml ; Begin Overloaded Var Sorting If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; End Overloaded Var Sorting $sectionNode = $xml.SelectSingleNode($path); if not $sectionNode $parentNode = $xml for each $node in split($path,"/") $p = $p + $node $sectionNode = $xml.SelectSingleNode($p)
if not $sectionNode $sectionNode = $xml.CreateElement($node) $parentNode = $parentNode.AppendChild($sectionNode) else $parentNode = $sectionNode endif $p = $p + "/" next endif
if $sectionNode $sectionNode.Text = $value endif ; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. Since the object was passed by ref, no further ; action necessary. Else If Instr($source,"<")=0 ; A file name was passed, so we write it out and destory the object SaveXML($xml, $source) $xml = 0 Else ; An XML string was passed ; Cannot save the XML string as we have no file name to save to ; so we return it. Since the object was passed by ref, no further ; action necessary.
EndIf EndIf ; End Overloaded Var Exit Strategy endfunction
|
jtokach
|
(Seasoned Scripter)
|
2005-03-19 12:24 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Ok, I'm not updating any one particular post anymore, it's too confusing. Here's all of the latest code that I have. Still a lot of work to be done, and I wont be doing any over the weekend if anyone is bored, but we have a basic working model.
Code:
Break On
$nul=SetOption("ASCII","On")
$nul=SetOption("Explicit","On")
Dim $filename1, $filename2, $filename3
Dim $xml, $
; This is an example by object
$filename1 = "C:\KiXtartByObject.xml"
$xml = LoadXml($filename1)
$= WriteXmlValue($xml, "korg/shawn/number", 119)
$= WriteXmlValue($xml, "korg/jose/number", 1772)
$= WriteXmlValue($xml, "korg/jooel/number", 2087)
$= WriteXmlValue($xml, "korg/jim/number",3555)
$= WriteXMLAttr($xml, "korg/jim", "Id", 3555)
$= WriteXMLAttr($xml, "korg/jim", "Age", 31)
SaveXml($xml, $filename1)
$xml = 0
; This is an example by filename
$filename2 = "C:\KiXtartByFileName.xml"
$= WriteXmlValue($filename2, "korg/shawn/number", 119)
$= WriteXmlValue($filename2, "korg/jose/number", 1772)
$= WriteXmlValue($filename2, "korg/jooel/number", 2087)
$= WriteXmlValue($filename2, "korg/jim/number",3555)
$= WriteXMLAttr($filename2, "korg/jim", "Id", 3555)
$= WriteXMLAttr($filename2, "korg/jim", "Age", 31)
? "Jim's age: " ReadXMLAttr($filename2, "korg/jim", "Age")
? "Jose's Number: " ReadXmlValue($filename2, "korg/jose/number")
$xml = 0
; This is an example by XML String
$filename3 = "C:\KiXtartByXMLString.xml"
Dim $strXML,$objXML
$strXML = "<korg><jim><E-mail>jim@@foo.com</E-mail></jim></korg>"
$strXML = WriteXmlValue($strXML, "korg/jim/id",3555)
; Note that after the initial write, the return becomes an object, therefore
; capturing the returns isn't necessary, but doesn't hurt either and is consistent.
$strXML = WriteXmlValue($strXML, "korg/jim/height",6)
$strXML = WriteXmlValue($strXML, "korg/jim/weight",230)
$strXML = WriteXmlValue($strXML, "korg/jim/eyes",2)
$strXML = WriteXMLAttr($strXML, "korg/jim", "Age", 31)
$strXML = WriteXMLAttr($strXML, "korg/jim", "Drink", "Beer")
? "Jim's age: " ReadXMLAttr($strXML, "korg/jim", "Age")
SaveXml($strXML, $filename3)
? "Jim's Drink: " ReadXMLAttr($filename3, "korg/jim", "Age")
$ = RemoveXMLAttr($filename3, "korg/jim", "Age")
? "Jim's Drink: " ReadXMLAttr($filename3, "korg/jim", "Age")
$strXML = 0
exit 1
; CreateXMLElement() - Creates an empty element pair
Function CreateXMLElement()
EndFunction
; EnumXMLAttr() - Enums all attributes of an element
Function EnumXMLAttr()
EndFunction
; EnumXMLElement() - Enums child elements of a given element
Function EnumXMLElement()
EndFunction
;FormatXML() - Formats the output style of an XMLDOM object to the standard
Function FormatXML($objXMLDOM)
;? "V" vartype($objXMLDOM)
Dim $,$strXSL,$objXSL
;Create and Load XSL
; <?xml version="1.0" encoding="UTF-8"?>
; <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
; <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
; <xsl:template match="/ | @* | node()">
; <xsl:copy>
; <xsl:apply-templates select="@* | node()" />
; </xsl:copy>
; </xsl:template>
; </xsl:stylesheet>
$strXSL = "<?xml version=" + chr(34) + "1.0" + chr(34) + " encoding=" +
chr(34) + "UTF-8" + chr(34) + "?>" + @CRLF
$strXSL = $strXSL + "<xsl:stylesheet version=" + chr(34) + "1.0" + chr(34) +
" xmlns:xsl=" + chr(34) + "http://www.w3.org/1999/XSL/Transform" +
chr(34) + ">" + @CRLF
$strXSL = $strXSL + "<xsl:output method=" + chr(34) + "xml" + chr(34) +
" version=" + chr(34) + "1.0" + chr(34) + " encoding=" + chr(34) +
"UTF-8" + chr(34) + " indent=" + chr(34) + "yes" + chr(34) + "/>" + @CRLF
$strXSL = $strXSL + "<xsl:template match=" + chr(34) + "/ | @@* | node()" +
chr(34) + ">" + @CRLF
$strXSL = $strXSL + "<xsl:copy>"+ @CRLF
$strXSL = $strXSL + "<xsl:apply-templates select=" + chr(34) +
"@@* | node()" + chr(34) + " />"+ @CRLF
$strXSL = $strXSL + "</xsl:copy>"+ @CRLF
$strXSL = $strXSL + "</xsl:template>"+ @CRLF
$strXSL = $strXSL + "</xsl:stylesheet>"
;? "XLM Stylesheet: " + @CRLF + $strXSL
$objXSL = CreateObject("Microsoft.XMLDOM")
$objXSL.async = false
$=$objXSL.loadXML($strXSL)
;Transform file
$objXMLDOM.TransformNodeToObject ($objXSL, $objXMLDOM)
$formatXML = $objXMLDOM
EndFunction
;LoadXML() - Load an existing .XML file, instantiate XMLDOM object for use
;regardless of file existance.
Function LoadXML($filename)
dim $, $rootNode, $objNewPI, $strType
$loadXml = CreateObject("Microsoft.XMLDOM")
$loadXml.async = False
$loadXml.preserverwhitespace = True
if not $loadXml
return
endif
$ = $loadXml.Load($filename)
EndFunction
; ReadXMLAttr() - Read a specific attribute of an XML element
Function ReadXMLAttr($source, $Path, $Attr)
Dim $SelectionTag,$AttrName,$,$xml
; *** Begin Overloaded Var Sorting ***
If VarType($source) = 9
; An object was passed
$xml = $source
Else
If Instr($source,"<")=0
; A file name was passed
$xml = LoadXML($source)
Else
; An XML string was passed
$xml = CreateObject("Microsoft.XMLDOM")
$xml.async = false
$=$xml.loadXML($source)
EndIf
EndIf
; *** End Overloaded Var Sorting ***
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrName = $SelectionTag.item(0)
If @ERROR = "-2147352573"
$ReadXMLAttr = ""
Exit @Error
Else
$ReadXMLAttr =$AttrName.getAttribute($Attr)
EndIf
; Begin Overloaded Var Exit Strategy
; None needed
; End Overloaded Var Exit Strategy
EndFunction
;ReadXMLElement() - Reads the value of an XML element
Function ReadXMLValue($source, $key, optional $defaultValue)
Dim $sectionNode,$xml,$
; *** Begin Overloaded Var Sorting ***
If VarType($source) = 9
; An object was passed
$xml = $source
Else
If Instr($source,"<")=0
; A file name was passed
$xml = LoadXML($source)
Else
; An XML string was passed
$xml = CreateObject("Microsoft.XMLDOM")
$xml.async = false
$=$xml.loadXML($source)
EndIf
EndIf
; *** End Overloaded Var Sorting ***
$sectionNode = $xml.SelectSingleNode($key)
If not $sectionNode
$ReadXmlValue = $defaultValue
Else
$ReadXmlValue = $sectionNode.FirstChild.Text
EndIf
EndFunction
; RemoveXMLAttr() - Deletes an XML element attribute
Function RemoveXMLAttr($source, $Path, $attr, optional $id)
Dim $SelectionTag,$AttrTag,$erase,$,$xml
; *** Begin Overloaded Var Sorting ***
If VarType($source) = 9
; An object was passed
$xml = $source
Else
If Instr($source,"<")=0
; A file name was passed
$xml = LoadXML($source)
Else
; An XML string was passed
$xml = CreateObject("Microsoft.XMLDOM")
$xml.async = false
$=$xml.loadXML($source)
EndIf
EndIf
; *** End Overloaded Var Sorting ***
$SelectionTag = $xml.getElementsByTagName($Path)
If $id=""
$id=0
EndIf
$AttrTag = $SelectionTag.item($id)
$erase = $AttrTag.removeAttribute($attr)
; Begin Overloaded Var Exit Strategy
If VarType($source) = 9
; An object was passed.
$RemoveXMLAttr = $xml
Else
If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object
SaveXML($xml, $source)
Else
; An XML string was passed.
$RemoveXMLAttr = $xml
EndIf
EndIf
; End Overloaded Var Exit Strategy
EndFunction
; RemoveXMLElement() - Deletes an XML element (Recursively?)
Function RemoveXMLElement()
EndFunction
;SaveXML() - Saves an XMLDOM object to a file
; Requires: FormatXML()
Function SaveXML($xml, $filename)
$xml = FormatXML($xml)
$SaveXml = $xml.Save($filename)
EndFunction
Function WriteXMLAttr($source, $Path, $Attr, $Value)
Dim $SelectionTag,$AttrTag,$,$Write,$xml
; *** Begin Overloaded Var Sorting ***
If VarType($source) = 9
; An object was passed
$xml = $source
Else
If Instr($source,"<")=0
; A file name was passed
$xml = LoadXML($source)
Else
; An XML string was passed
$xml = CreateObject("Microsoft.XMLDOM")
$xml.async = false
$=$xml.loadXML($source)
EndIf
EndIf
; *** End Overloaded Var Sorting ***
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
If @ERROR = "-2147352573"
$ = WriteXmlValue($xml, $path, "")
$SelectionTag = $xml.getElementsByTagName($Path)
$AttrTag = $SelectionTag.item(0)
EndIf
$write = $AttrTag.SetAttribute($Attr,$Value)
; Begin Overloaded Var Exit Strategy
If VarType($source) = 9
; An object was passed.
$WriteXMLAttr = $xml
Else
If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object
SaveXML($xml, $source)
Else
; An XML string was passed.
$WriteXMLAttr = $xml
EndIf
EndIf
; End Overloaded Var Exit Strategy
EndFunction
; WriteXMLValue() - Writes a value to an XML element
Function WriteXMLValue($source, $path, $value)
dim $, $p, $rootNode, $sectionNode, $parentNode, $childNode, $node, $xml
; *** Begin Overloaded Var Sorting ***
If VarType($source) = 9
; An object was passed
$xml = $source
Else
If Instr($source,"<")=0
; A file name was passed
$xml = LoadXML($source)
Else
; An XML string was passed
$xml = CreateObject("Microsoft.XMLDOM")
$xml.async = false
$=$xml.loadXML($source)
EndIf
EndIf
; *** End Overloaded Var Sorting ***
$sectionNode = $xml.SelectSingleNode($path);
if not $sectionNode
$parentNode = $xml
for each $node in split($path,"/")
$p = $p + $node
$sectionNode = $xml.SelectSingleNode($p)
if not $sectionNode
$sectionNode = $xml.CreateElement($node)
$parentNode = $parentNode.AppendChild($sectionNode)
else
$parentNode = $sectionNode
endif
$p = $p + "/"
next
endif
if $sectionNode
$sectionNode.Text = $value
endif
; Begin Overloaded Var Exit Strategy
If VarType($source) = 9
; An object was passed.
$WriteXMLValue = $xml
Else
If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object
SaveXML($xml, $source)
Else
; An XML string was passed.
$WriteXMLValue = $xml
EndIf
EndIf
; End Overloaded Var Exit Strategy
endfunction
; ******************************************************************************
; ApplyXSL() - Applies an XSL template. (Much potential here for an expanded
; set, see http://www.devguru.com/Technologies/xslt/quickref/xslt_index.html
Function ApplyXSL()
EndFunction
; FilterXML() - Apply a filter to an XMLDOM object. (Search the db. XSL related.)
Function FilterXML()
EndFunction
Function EnumXML($source)
dim $nodelist,$i
$NodeList = $source.getElementsByTagName("*")
For Each $i In $NodeList
? "Element " +$i.tagName
;? "attributes: " $i.attributes
;? "baseName: " $i.baseName
;? "childNodes: " $i.childNodes
;? "dataType: " $i.dataType
;? "definition: " $i.definition
;? "firstChild: " $i.firstChild.nodeName
;? "lastChild: " $i.lastChild.nodeName
;? "namespaceURI: " $i.namespaceURI
;? "nextSibling: " $i.nextSibling.nodeName
;? "nodeName: " $i.nodeName
;? "nodeType: " $i.nodeType
;? "nodeTypeString: " $i.nodeTypeString
;? "nodeValue: " $i.nodeValue
;? "ownerDocument: " $i.ownerDocument
;? "parentNode: " $i.parentNode.nodeName
;? "parsed: " $i.parsed
;? "prefix: " $i.prefix
;? "previousSibling: " $i.previousSibling.nodeName
;? "specified: " $i.specified
;? "tagName: " $i.tagName
;? "text: " $i.text
? "xml: " $i.xml
?
Next
EndFunction
|
jtokach
|
(Seasoned Scripter)
|
2005-03-23 01:13 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
I think wraps it up, except for the XSL stuff. The ENUM's return collections. Haven't done a decent amount of testing with all of this and error checking is weak.
Code:
Break On $nul=SetOption("ASCII","On") $nul=SetOption("Explicit","On") $nul=SetOption("WrapAtEOL","On")
Dim $filename1, $filename2, $filename3 Dim $xml, $
; This is an example by object $filename1 = "C:\KiXtartByObject.xml"
$xml = LoadXml($filename1)
$= WriteXmlValue($xml, "korg/shawn/number", 119) $= WriteXmlValue($xml, "korg/jose/number", 1772) $= WriteXmlValue($xml, "korg/jooel/number", 2087) $= WriteXmlValue($xml, "korg/jim/number",3555)
$= WriteXMLAttr($xml, "korg/jim", "Id", 3555) $= WriteXMLAttr($xml, "korg/jim", "Age", 31) $= WriteXMLAttr($xml, "korg/jose", "Id", 4565) $= WriteXMLAttr($xml, "korg/jose", "Age", 22) $= WriteXMLAttr($xml, "korg/admins/jim", "Id", 1234) $= WriteXMLAttr($xml, "korg/admins/jim", "Age", 58)
SaveXml($xml, $filename1) $xml = 0
; This is an example by filename $filename2 = "C:\KiXtartByFileName.xml"
$= WriteXmlValue($filename2, "korg/shawn/number", 119) $= WriteXmlValue($filename2, "korg/jose/number", 1772) $= WriteXmlValue($filename2, "korg/jooel/number", 2087) $= WriteXmlValue($filename2, "korg/jim/number",3555)
$= WriteXMLAttr($filename2, "korg/jim", "Id", 3555) $= WriteXMLAttr($filename2, "korg/jim", "Age", 31)
? "Jim's age: " ReadXMLAttr($filename2, "korg/jim", "Age") ? "Jose's Number: " ReadXmlValue($filename2, "korg/jose/number")
$xml = 0
; This is an example by XML String $filename3 = "C:\KiXtartByXMLString.xml" Dim $strXML,$objXML
$strXML = "<korg><jim><E-mail>jim@@foo.com</E-mail></jim></korg>" $strXML = WriteXmlValue($strXML, "korg/jim/id",3555) ; Note that after the initial write, the return becomes an object, therefore ; capturing the returns isn't necessary, but doesn't hurt either and is consistent. $strXML = WriteXmlValue($strXML, "korg/jim/height",6) $strXML = WriteXmlValue($strXML, "korg/jim/weight",230) $strXML = WriteXmlValue($strXML, "korg/jim/eyes",2)
$strXML = WriteXMLAttr($strXML, "korg/jim", "Age", 31) $strXML = WriteXMLAttr($strXML, "korg/jim", "Drink", "Beer")
? "Jim's age: " ReadXMLAttr($strXML, "korg/jim", "Age") ? "Jim's Drink: " ReadXMLAttr($filename3, "korg/jim", "Drink") SaveXml($strXML, $filename3)
$ = RemoveXMLAttr($filename3, "korg/jim", "Age") ? "Jim's Age: " ReadXMLAttr($filename3, "korg/jim", "Age")
$strXML = 0
; Enumerate elements and attributes Dim $colE Dim $colXMLElements Dim $colAttrs,$colAttr ?? "Enuming All XML Elements" ; Return all elements in the XML file $colXMLElements = EnumXMLElement($filename1,"*") For Each $colE In $colXMLElements ? "XML Element Name : " + $colE.TagName ;? "XML Element Value: " + $colE.Text Next ?? "Enuming Child XML Elements of korg" ; Return all elements in the XML file $colXMLElements = EnumXMLElement($filename1,"korg/*") For Each $colE In $colXMLElements ? "XML Element Name : " + $colE.TagName ;? "XML Element Value: " + $colE.Text Next ?? "Enuming Child XML Elements of korg/shawn" ; Return all elements in the XML file $colXMLElements = EnumXMLElement($filename1,"korg/shawn/*") For Each $colE In $colXMLElements ? "XML Element Name : " + $colE.TagName ;? "XML Element Value: " + $colE.Text Next ?? "Enuming XML Number Elements and their values" ; Return all "number" elements and their value $colXMLElements = EnumXMLElement($filename1,"number") For Each $colE In $colXMLElements ? "XML Element Name : " + $colE.TagName ? "XML Element Value: " + $colE.Text Next ?? "Enuming XML Elements With Attributes and the attribute values (Without EnumXMLAttr)" ; Return all elements that have attributes and enum the attr the long way $colXMLElements = EnumXMLElement($filename1,"*") For Each $colE In $colXMLElements If $colE.Attributes.length > 0 ? "XML Element Name : " + $colE.TagName Dim $strAttr For Each $strAttr In $colE.Attributes ? " XML Attribute Name : " + $strAttr.Name ? " XML Attribute Value: " + $strAttr.Value Next EndIf Next ?? "Enuming XML Elements With Attributes and the attribute values (With EnumXMLAttr)" ; Return all elements that have attributes and enum the attr the long way $colXMLElements = EnumXMLElement($filename1,"*") For Each $colE In $colXMLElements If $colE.Attributes.length > 0 ? "XML Element Name : " + $colE.TagName $colAttrs = EnumXMLAttr($filename1,$colE.parentNode.nodeName+ "/" + $colE.TagName) For Each $colAttr In $colAttrs ? "XML Attribute Name : " + $colAttr.Name ? "XML Attribute Value: " + $colAttr.Value Next EndIf Next
?? "Enuming XML Attributes and the attribute values of a specific element (precise path)" $colAttrs = EnumXMLAttr($filename1,"korg/admins/jim") For Each $colAttr In $colAttrs ? "XML Attribute Name : " + $colAttr.Name ? "XML Attribute Value: " + $colAttr.Value Next ?? "Enuming XML Attributes and the attribute values of a specific element (parent only path)" $colAttrs = EnumXMLAttr($filename1,"admins/jim") For Each $colAttr In $colAttrs ? "XML Attribute Name : " + $colAttr.Name ? "XML Attribute Value: " + $colAttr.Value Next ?? "Enuming XML Attributes and the attribute values of the 1st element found called 'Jim'" $colAttrs = EnumXMLAttr($filename1,"jim") For Each $colAttr In $colAttrs ? "XML Attribute Name : " + $colAttr.Name ? "XML Attribute Value: " + $colAttr.Value Next ?? "Creating the forums..." $=CreateXMLElement($filename1,"korg/forums/starters") $=CreateXMLElement($filename1,"korg/forums/scripts") $=CreateXMLElement($filename1,"korg/forums/General Discussion") $=CreateXMLElement($filename1,"korg/forums/COM") $=CreateXMLElement($filename1,"korg/forums/UDF") $=CreateXMLElement($filename1,"korg/forums/UDFs") $=CreateXMLElement($filename1,"korg/forums/Beta") $=CreateXMLElement($filename1,"korg/forums/Examples") ?? "Listing forums" $colXMLElements = EnumXMLElement($filename1,"korg/forums/*") For Each $colE in $colXMLElements ? "Forum Name : " + $colE.TagName Next ?? "Deleting error" $ = RemoveXMLElement($filename1,"forums/UDF") ?? "Listing forums again" $colXMLElements = EnumXMLElement($filename1,"korg/forums/*") For Each $colE in $colXMLElements ? "Forum Name : " + $colE.TagName Next ?? "Deleting all forums" $ = RemoveXMLElement($filename1,"forums") ?? "Listing forums again" $colXMLElements = EnumXMLElement($filename1,"korg/forums/*") For Each $colE in $colXMLElements ? "Forum Name : " + $colE.TagName Next exit 1
; CreateXMLElement() - Creates an empty element pair Function CreateXMLElement($source,$path) $CreateXMLElement = WriteXMLValue($source,$path,"") EndFunction
; EnumXMLAttr() - Enums all attributes of an element Function EnumXMLAttr($source,$path) Dim $xml,$ ; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting *** Dim $colXMLElements,$colE $colXMLElements = $xml.getElementsByTagName($path) If $colXMLElements.item(0).Attributes.length > 0 $EnumXMLAttr = $colXMLElements.item(0).Attributes EndIf EndFunction
; EnumXMLElement() - Enums child elements of a given element Function EnumXMLElement($source,$path) Dim $xml,$ ; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting *** ;Select ; Case Right($path,1)= "/" ; $path = Left($path,Len($path)-1) ; ;? "path "$path ; $EnumXMLElement = $xml.getElementsByTagName($path).Item(0) ; $EnumXMLElement = $EnumXMLElement.ChildNodes ; Case 1 ; $EnumXMLElement = $xml.getElementsByTagName($path) ;EndSelect $EnumXMLElement = $xml.getElementsByTagName($path) EndFunction
;FormatXML() - Formats the output style of an XMLDOM object to the standard Function FormatXML($objXMLDOM)
;? "V" vartype($objXMLDOM)
Dim $,$strXSL,$objXSL ;Create and Load XSL ; <?xml version="1.0" encoding="UTF-8"?> ; <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> ; <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> ; <xsl:template match="/ | @* | node()"> ; <xsl:copy> ; <xsl:apply-templates select="@* | node()" /> ; </xsl:copy> ; </xsl:template> ; </xsl:stylesheet>
$strXSL = "<?xml version=" + chr(34) + "1.0" + chr(34) + " encoding=" + chr(34) + "UTF-8" + chr(34) + "?>" + @CRLF $strXSL = $strXSL + "<xsl:stylesheet version=" + chr(34) + "1.0" + chr(34) + " xmlns:xsl=" + chr(34) + "http://www.w3.org/1999/XSL/Transform" + chr(34) + ">" + @CRLF $strXSL = $strXSL + "<xsl:output method=" + chr(34) + "xml" + chr(34) + " version=" + chr(34) + "1.0" + chr(34) + " encoding=" + chr(34) + "UTF-8" + chr(34) + " indent=" + chr(34) + "yes" + chr(34) + "/>" + @CRLF $strXSL = $strXSL + "<xsl:template match=" + chr(34) + "/ | @@* | node()" + chr(34) + ">" + @CRLF $strXSL = $strXSL + "<xsl:copy>"+ @CRLF $strXSL = $strXSL + "<xsl:apply-templates select=" + chr(34) + "@@* | node()" + chr(34) + " />"+ @CRLF $strXSL = $strXSL + "</xsl:copy>"+ @CRLF $strXSL = $strXSL + "</xsl:template>"+ @CRLF $strXSL = $strXSL + "</xsl:stylesheet>"
;? "XLM Stylesheet: " + @CRLF + $strXSL
$objXSL = CreateObject("Microsoft.XMLDOM") $objXSL.async = false $=$objXSL.loadXML($strXSL)
;Transform file $objXMLDOM.TransformNodeToObject ($objXSL, $objXMLDOM) $formatXML = $objXMLDOM EndFunction
;LoadXML() - Load an existing .XML file, instantiate XMLDOM object for use ;regardless of file existance. Function LoadXML($filename) dim $, $rootNode, $objNewPI, $strType
$loadXml = CreateObject("Microsoft.XMLDOM") $loadXml.async = False $loadXml.preserverwhitespace = True
if not $loadXml return endif
$ = $loadXml.Load($filename) EndFunction
; ReadXMLAttr() - Read a specific attribute of an XML element Function ReadXMLAttr($source, $Path, $Attr) Dim $SelectionTag,$AttrName,$,$xml ; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting ***
$SelectionTag = $xml.getElementsByTagName($Path) $AttrName = $SelectionTag.item(0) If @ERROR = "-2147352573" $ReadXMLAttr = "" Exit @Error Else $ReadXMLAttr =$AttrName.getAttribute($Attr) EndIf
; Begin Overloaded Var Exit Strategy ; None needed ; End Overloaded Var Exit Strategy EndFunction
;ReadXMLElement() - Reads the value of an XML element Function ReadXMLValue($source, $key, optional $defaultValue) Dim $sectionNode,$xml,$
; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting ***
$sectionNode = $xml.SelectSingleNode($key) If not $sectionNode $ReadXmlValue = $defaultValue Else $ReadXmlValue = $sectionNode.FirstChild.Text EndIf EndFunction
; RemoveXMLAttr() - Deletes an XML element attribute Function RemoveXMLAttr($source, $Path, $attr, optional $id) Dim $SelectionTag,$AttrTag,$erase,$,$xml
; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting *** $SelectionTag = $xml.getElementsByTagName($Path) If $id="" $id=0 EndIf $AttrTag = $SelectionTag.item($id) $erase = $AttrTag.removeAttribute($attr)
; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. $RemoveXMLAttr = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object SaveXML($xml, $source) Else ; An XML string was passed. $RemoveXMLAttr = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy
EndFunction
; RemoveXMLElement() - Deletes an XML element (Recursively?) Function RemoveXMLElement($source,$path) Dim $SelectionTag,$AttrTag,$,$xml
; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting ***
$SelectionTag = $xml.getElementsByTagName($path) Dim $i
For $i=0 To $SelectionTag.Length - 1 ;? "Index "$i ;? "Removing "$SelectionTag.item($i).TagName ;? "Parent " $SelectionTag.item($i).ParentNode.TagName $=$SelectionTag.item($i).ParentNode.RemoveChild($SelectionTag.item($i)) ;? @Serror Next
; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. $RemoveXMLElement = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object SaveXML($xml, $source) Else ; An XML string was passed. $RemoveXMLElement = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy EndFunction
;SaveXML() - Saves an XMLDOM object to a file ; Requires: FormatXML() Function SaveXML($xml, $filename) $xml = FormatXML($xml) $SaveXml = $xml.Save($filename) EndFunction
Function WriteXMLAttr($source, $Path, $Attr, $Value) Dim $SelectionTag,$AttrTag,$,$Write,$xml
; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting ***
$SelectionTag = $xml.getElementsByTagName($Path) $AttrTag = $SelectionTag.item(0) If @ERROR = "-2147352573" $ = WriteXmlValue($xml, $path, "") $SelectionTag = $xml.getElementsByTagName($Path) $AttrTag = $SelectionTag.item(0) EndIf $write = $AttrTag.SetAttribute($Attr,$Value)
; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. $WriteXMLAttr = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object SaveXML($xml, $source) Else ; An XML string was passed. $WriteXMLAttr = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy EndFunction
; WriteXMLValue() - Writes a value to an XML element Function WriteXMLValue($source, $path, $value) dim $, $p, $rootNode, $sectionNode, $parentNode, $childNode, $node, $xml
; *** Begin Overloaded Var Sorting *** If VarType($source) = 9 ; An object was passed $xml = $source Else If Instr($source,"<")=0 ; A file name was passed $xml = LoadXML($source) Else ; An XML string was passed $xml = CreateObject("Microsoft.XMLDOM") $xml.async = false $=$xml.loadXML($source) EndIf EndIf ; *** End Overloaded Var Sorting ***
$sectionNode = $xml.SelectSingleNode($path);
if not $sectionNode $parentNode = $xml
for each $node in split($path,"/") $p = $p + $node $sectionNode = $xml.SelectSingleNode($p) if not $sectionNode $sectionNode = $xml.CreateElement($node) $parentNode = $parentNode.AppendChild($sectionNode) else $parentNode = $sectionNode endif $p = $p + "/" next endif
if $sectionNode $sectionNode.Text = $value endif
; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. $WriteXMLValue = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object SaveXML($xml, $source) Else ; An XML string was passed. $WriteXMLValue = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy
endfunction
; ****************************************************************************** ; ApplyXSL() - Applies an XSL template. (Much potential here for an expanded ; set, see http://www.devguru.com/Technologies/xslt/quickref/xslt_index.html Function ApplyXSL()
EndFunction
; FilterXML() - Apply a filter to an XMLDOM object. (Search the db. XSL related.) Function FilterXML()
EndFunction
Function EnumXML($source) dim $nodelist,$i $NodeList = $source.getElementsByTagName("*") For Each $i In $NodeList ? "Element " +$i.tagName ;? "attributes: " $i.attributes ;? "baseName: " $i.baseName ;? "childNodes: " $i.childNodes ;? "dataType: " $i.dataType ;? "definition: " $i.definition ;? "firstChild: " $i.firstChild.nodeName ;? "lastChild: " $i.lastChild.nodeName ;? "namespaceURI: " $i.namespaceURI ;? "nextSibling: " $i.nextSibling.nodeName ;? "nodeName: " $i.nodeName ;? "nodeType: " $i.nodeType ;? "nodeTypeString: " $i.nodeTypeString ;? "nodeValue: " $i.nodeValue ;? "ownerDocument: " $i.ownerDocument ;? "parentNode: " $i.parentNode.nodeName ;? "parsed: " $i.parsed ;? "prefix: " $i.prefix ;? "previousSibling: " $i.previousSibling.nodeName ;? "specified: " $i.specified ;? "tagName: " $i.tagName ;? "text: " $i.text ? "xml: " $i.xml ? Next EndFunction
|
NTDOC
|
(KiX Master)
|
2005-03-23 08:38 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Well not exactly in the KiX coding area thought I'd pass along these links for doing, learning XML data with Excel.
Excel 2003 Add-in: XML Tools Add-in Overview Learn how to use the Microsoft Office Excel 2003 XML Tools Add-in Version 1.1. With it, you can provide information about a selected cell's XML properties, create XSD files for XML maps, rename the Root and Row elements, or refresh all of the XML maps in a workbook at once. http://www.microsoft.com/downloads/detai...;displaylang=en
Using the Excel 2003 XML Tools Add-in James Rivera and Frank Rice show how this new add-in makes working with XML maps, cells, and ranges much easier for developers. (February 2005) http://msdn.microsoft.com/office/underst...mltooladdin.asp
Part 1: Automating the XML Data Mapping Process in Excel 2003 Learn how to use XML maps to customize Excel as a data input and display system. (March 2005) http://msdn.microsoft.com/office/underst...ata_mapping.asp
Part 2: Mapping XML from SQL Server to a Single Cell in Excel 2003 In the second of this three-part series, learn how to map well-formed XML from a standard SQL Server query to a single cell in a worksheet. The resulting output is an XML tree with non-repeating elements. (March 2005) http://msdn.microsoft.com/office/underst..._sql_server.asp
Create XML Mappings in Excel 2003 Walk through common XML tasks in Excel 2003 to learn more about the new XML functionality in Office 2003 Editions. Learn how to add custom schemas, work with XML maps in Excel, and create a series of mappings based on various schemas. (February 2005) http://msdn.microsoft.com/office/underst...ngscenarios.asp
How Excel 2003 Infers XSDs when Importing XML Data Review the rules and instances where Excel 2003 infers schema from XML data during import and export. Understand why Excel creates the schemas it does and then learn to modify your own XML data. (February 2005) http://msdn.microsoft.com/office/underst...nferdetails.asp
|
jtokach
|
(Seasoned Scripter)
|
2005-03-23 10:23 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Hmmm... The rating on this post went from 5 to 3 three stars... Someone is obviously not happy with something. Please speak your mind rather than let this go down the wrong development path.
|
Jose
|
(Seasoned Scripter)
|
2005-03-25 06:01 AM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Hey Jim wonderfull work man!!. Very complete piece of UDF´s. Sorry I didnt have the time to give you some feedback but I played with it and looks very good. I see you have dealed with RemoveXMLElement() good.
So far..
LoadXML() FormatXML()
WriteXmlValue() CreateXMLElement() WriteXMLAttr()
ReadXMLValue() ReadXMLAttr()
EnumXMLElement() EnumXMLAttr()
RemoveXMLAttr() RemoveXMLElement()
SaveXML()
About XML I have seen resistance notisted at suggestion forum but I think this is kinda normal not specially with XML but for other languajes known as foreings to Kixtart FE Flash,java etc. But it is understandable cause kix makes you love it jealously.
What I really see positive about this thead it that lot have been done since your first suggetion.
Quote:
Not sure if this is practical, but I'll throw it out there. With .XML becoming more and more prevalent, wouldn't it be nice to have functions to manipulate .XML files like the functions we have to manipulate .INI files?
Well...acomplish has been made. A rate is deserved. Now its time to wait for dear Shawn to speack up about posting as UDF´s. Me going to country side till monday and that makes me happy.
DOC: I dont have Excel 2003 so as to try your links.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-25 07:25 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Thanks Jose! I was beginning to think this would never see the light of day. Thank Shawn and Chris for renewed spark of interest; add a little elbow grease and voila.
Hope you enjoy your mini-vacation! I'll be writing Use-Case scenarios this weekend for a class I'm taking. That sucks.
Shawn, I suppose we shouldv'e put together a use-case diagram before hammering these out.
|
Shawn
|
(KiX Supporter)
|
2005-03-25 07:39 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
use-case diagram ? that anything like flow-charts and gant-charts ? ;0) (idk)
I have been incorporating these XML ideas/strategies into my GRID script (a kinda Excel work-alike) ... the raw native XML functions work very fast - much faster than using INI's ... but ... the UDF's are much slower, even slower then INI's ... has to do with the ReadXmlValue UDF me thinks ... think that one needs a bit of tweaking ...
When done, will give the UDF's a try (again), and apply any lesson's learned to them, hopefully make them much faster than INI's ...
-Shawn
|
jtokach
|
(Seasoned Scripter)
|
2005-03-25 07:51 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Use-Cases are part of UML somewhere. See: Link I'll take a look at ReadXmlValue()
|
jtokach
|
(Seasoned Scripter)
|
2005-03-25 08:40 PM
|
|
|
|
|
Re: RFC: ReadXmlString/WriteXmlString
|
|
Starting a new thread here.
|