jtokach
|
(Seasoned Scripter)
|
2005-03-25 08:39 PM
|
|
|
|
|
RFC: XML UDF's
|
|
Started a new topic due to size. Continued from here.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-25 08:45 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Shawn, we've got a problem. The current setup of WriteXMLvalue, and probably every other UDF doesn't support this type of layout: Code:
<korg> <users> <id>1</id> <id>2</id> <id>3</id> <id>4</id> <id>5</id> </users> </korg>
Back to the drawing board...
|
Lonkero
|
(KiX Master Guru)
|
2005-03-25 11:50 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Quote:
and probably every other UDF doesn't
please be more specific.
|
jtokach
|
(Seasoned Scripter)
|
2005-03-27 12:21 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
All of the XML UDF's we've put together.
|
Shawn
|
(KiX Supporter)
|
2005-03-28 08:07 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jim,
I'm still working muchly with the "raw" XML functions. Lessons learned so far:
1) Reading Attributes of a node is much, much faster than reading child-elements (of the node) containing the same information... for example reading this:
Code:
<node1> <data1>1</data1> <data2>2</data2> </node1>
is much slower then reading this:
Code:
<node1 data1="1" data2="2"> </node1>
Probably this has more to do with how one would "design" their schema, versus the UDF's themselves - just an observation.
-Shawn
|
jtokach
|
(Seasoned Scripter)
|
2005-03-28 08:18 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Indeed, that makes sense; less parsing, more direct. Also agreed, more for planning purposes than anything else. I'll see what I can up with regarding the issue above.
|
Shawn
|
(KiX Supporter)
|
2005-03-28 08:41 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
I complained earlier in another thread - that it seemed a "waste" to have create an element as a child of the entire document, then later to have to add the element as a child of some other element ....
Lesson learned number two:
This isn't necessarily a bad thing - I learned that it is advantageous to be able to create an element, and to populate it with attributes and sub-elements - then to be able to later make the determination whether to actually add it as a child.
This ability really helped me in my GRID script - i was able to skip-over having to save CELL elements that only contained default settings (therefore don't need to be saved) - this speeds up the "loading" of the grid later on.
-Shawn
|
Shawn
|
(KiX Supporter)
|
2005-03-28 08:57 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Having a "messy" XML file isn't necessarily a "bad thing", if one has a half-decent XML editor/viewer to edit/view with ;0)
Lesson learned number #3 - messy XML aint the end of the world ... here's a sample of my GRID (spread-sheet) like schema so far...
<Grid RowCount="11" ColumnCount="3" AllowSorting="-1" AlternatingBackColor="-1" BackColor="16777215" ColumnHeaderStyle="2" CurrentColumnIndex="0" CurrentRowIndex="0" FontName="Verdana" FontSize="8" ForeColor="0" FullRowSelect="0" GridColor="8421504" GridLines="3" MultiSelect="0" ReadOnly="0" SingleClickEdit="0"> - <Columns> <Column.0 Index="0" Alignment="-1" AllowSorting="-1" BackColor="-1" CellType="-1" ForeColor="-1" Format="" HeaderText="CategoryID" ImageIndex="-1" MinimumWidth="15" Name="CategoryID" ReadOnly="0" Resizable="-1" Width="100" ValueType="5" /> <Column.1 Index="1" Alignment="-1" AllowSorting="-1" BackColor="-1" CellType="-1" ForeColor="-1" Format="" HeaderText="CategoryName" ImageIndex="-1" MinimumWidth="15" Name="CategoryName" ReadOnly="0" Resizable="-1" Width="100" ValueType="8" /> <Column.2 Index="2" Alignment="-1" AllowSorting="-1" BackColor="-1" CellType="-1" ForeColor="-1" Format="" HeaderText="Description" ImageIndex="-1" MinimumWidth="15" Name="Description" ReadOnly="0" Resizable="-1" Width="100" ValueType="8" /> </Columns> - <Cells> <Cell.0.0 Value="1" RowIndex="0" ColumnIndex="0" /> <Cell.0.1 Value="Beverages" RowIndex="0" ColumnIndex="1" /> <Cell.0.2 Value="Soft drinks, coffees, teas, beers, and ales" RowIndex="0" ColumnIndex="2" /> <Cell.1.0 Value="2" RowIndex="1" ColumnIndex="0" /> <Cell.1.1 Value="Condiments" RowIndex="1" ColumnIndex="1" /> <Cell.1.2 Value="Sweet and savory sauces, relishes, spreads, and seasonings" RowIndex="1" ColumnIndex="2" /> <Cell.2.0 Value="3" RowIndex="2" ColumnIndex="0" /> <Cell.2.1 Value="Confections" RowIndex="2" ColumnIndex="1" /> <Cell.2.2 Value="Desserts, candies, and sweet breads" RowIndex="2" ColumnIndex="2" /> <Cell.3.0 Value="4" RowIndex="3" ColumnIndex="0" /> <Cell.3.1 Value="Dairy Products" RowIndex="3" ColumnIndex="1" /> <Cell.3.2 Value="Cheeses" RowIndex="3" ColumnIndex="2" /> <Cell.4.0 Value="5" RowIndex="4" ColumnIndex="0" /> <Cell.4.1 Value="Grains/Cereals" RowIndex="4" ColumnIndex="1" /> <Cell.4.2 Value="Breads, crackers, pasta, and cereal" RowIndex="4" ColumnIndex="2" /> <Cell.5.0 Value="6" RowIndex="5" ColumnIndex="0" /> <Cell.5.1 Value="Meat/Poultry" RowIndex="5" ColumnIndex="1" /> <Cell.5.2 Value="Prepared meats" RowIndex="5" ColumnIndex="2" /> <Cell.6.0 Value="7" RowIndex="6" ColumnIndex="0" /> <Cell.6.1 Value="Produce" RowIndex="6" ColumnIndex="1" /> <Cell.6.2 Value="Dried fruit and bean curd" RowIndex="6" ColumnIndex="2" /> <Cell.7.0 Value="8" RowIndex="7" ColumnIndex="0" /> <Cell.7.1 Value="Seafood" RowIndex="7" ColumnIndex="1" /> <Cell.7.2 Value="Seaweed and fish" RowIndex="7" ColumnIndex="2" /> <Cell.8.0 Value="13" RowIndex="8" ColumnIndex="0" /> <Cell.8.1 Value="ssss" RowIndex="8" ColumnIndex="1" /> <Cell.9.0 Value="14" RowIndex="9" ColumnIndex="0" /> <Cell.9.1 Value="xxxx" RowIndex="9" ColumnIndex="1" /> <Cell.10.0 Value="9" RowIndex="10" ColumnIndex="0" /> <Cell.10.1 Value="Shawn" RowIndex="10" ColumnIndex="1" /> </Cells> </Grid>
|
Jose
|
(Seasoned Scripter)
|
2005-03-29 10:17 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Shawn just to add to this story I have seen on a simple google search that attributes are known to be fast but there is reason why.
Reference
Quote:
The primary key in an XML structure, the one used to identify specific objects, has a requirement that it be unique. Typically for XML structures, this uniqueness will come in the form of an ID of some sort. For the sample characters document, the ID is actually an attribute called "id" attached to the node. Because most parsers are able to parse attributes faster than elements and because an ID is less a describing property of the object and more a name for that object, you should keep IDs and ID references as attributes within your document structure for best efficiency.
But using attributes as child element has its problems too.
Quote:
Some of the problems with using attributes are:
* attributes cannot contain multiple values (child elements can) * attributes are not easily expandable (for future changes) * attributes cannot describe structures (child elements can) * attributes are more difficult to manipulate by program code * attribute values are not easy to test against a Document Type Definition (DTD) - which is used to define the legal elements of an XML document.
If you use attributes as containers for data, you end up with documents that are difficult to read and maintain. Try to use elements to describe data. Use attributes only to provide information that is not relevant to the data.
|
Jose
|
(Seasoned Scripter)
|
2005-04-21 08:11 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
I have been doing some XML and noticed that in WriteXMLValue($source, $path, $value) any child included in the path cannot start with a number, otherwise you get error. Example: Code:
$= WriteXmlValue($xml, "korg/shawn/1_number", 119)
|
Jose
|
(Seasoned Scripter)
|
2005-04-26 01:49 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Shawn, Jim: I find these new UDF´s very intresting and usefull but still there is something I cannot do with them.
It is ideal and for a better xml structure to store data on an XML file using the attribute as a table Id like this: Code:
<messages> <note id="p501"> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note> <note id="p502"> <to>Jani</to> <from>Tove</from> <heading>Re: Reminder</heading> <body>I will not!</body> </note> </messages>
I found difficulties when you need to update an elemets that hangs from a a root value referenced with an attribute, FE (case above). I want to modify the body when id="p502".
If we can solve this I think there is gonna be little left to manipulate any XML with Kix.
Thanks boys.
BTW: Looks like 'without UBBcode/HTML' combo is not working.....mnn......yes it is, after I posted this modification...weird.
|
Shawn
|
(KiX Supporter)
|
2005-04-26 02:16 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jose/Jim.
I have been playing much with the XMLDOM object model and wrote a little script that helped me "explore" the model. Its actually quite instructive to poke around XMLDOM and see (visually) just how "strange" it is.
If you want to check it out (the work-in-progress), I posted it here:
XML Workshop
You need the latest kixforms dev build to run this, here:
Kixforms Development Build
Would love to get your feedback/observations on this.
-Shawn
|
Jose
|
(Seasoned Scripter)
|
2005-04-26 07:19 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Well Shawn you have really done some difference here. Very nice man!! . I will give a try tomorrow at and post some feedback.
About what I have asked above about the element uptade according to the attr (similar to id of table), now that Shawn is an XMLDOM expert he had fixed a code that does the task wich can perfectly fit to a new UDF. Here is the code: Code:
<?xml version="1.0" encoding="UTF-8"?> <messages> <note id="p501"> <to>Jani</to> <from>Jani</from> <heading>Reminder</heading> <body>Dont forget me this weekend!</body> </note> <note id="p502"> <to>Jani</to> <from>Tove</from> <heading>How are you</heading> <body>Gimme a call Tovy!!</body> </note> <note id="p503"> <to>Shawn</to> <from>Joser</from> <heading>Shawn you.....</heading> <body>.....are a wonderfull person</body> </note> </messages>
In wich case if I want to update <to> value of id="p501" attr would be something like this. It is rought script wet. Code:
UpdateFromAttribute('id', 'p501', 'body', 'Dont forget me this weekend!...please')
Code:
Function UpdateFromAttribute($Attr, $AttrValue, $Path, $PathValue) For Each $note In $xml.documentelement.childnodes If $note.getattribute($Attr) = $AttrValue $heading = $note.selectsinglenode($Path) $heading.text = $PathValue EndIf Next EndFunction
|
jtokach
|
(Seasoned Scripter)
|
2005-04-26 06:15 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jose,
There are several problems with the current UDF's which I didn't realize until afterwards; my second post in this thread being the main problem. I really haven't had time to come back to this and probably wont for a few weeks. Of course, if Shawn has developed a better model, we can choose to emulate it in Kix so that they are independant of the kixforms.dll. It certainly wont be anywhere near as fast though but at least they'll jive.
|
Shawn
|
(KiX Supporter)
|
2005-04-26 06:39 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
I didn't devise a new model, just wrote a kixscript that allows one to "explore" the existing XMLDOM model. It presents a TreeView on the left, with all the nodes as they are presented by xmldom. On the right, one can see all the xmldom properties. There is another Tab for xml view.
-Shawn
|
jtokach
|
(Seasoned Scripter)
|
2005-04-26 06:49 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Ah, well then, these still need a major overhaul to cope with post #2 and jose's attribute thingys. We jumped into this without enough forethought. The specifications need to be changed to handle the above or a different model needs adoption. I think we have enough info and made enough mistakes to develop a solid set of UDF's here on out. Perhaps we can also consider performance this time through, or leave it for version 2.
|
Jose
|
(Seasoned Scripter)
|
2005-04-26 07:01 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
But Jim those "several problems" arent that bad. I have been using these udf's normally, besides there where none to use before so that is good. I say to go ahead shoot the UDF's and make corrections on the fly.
|
jtokach
|
(Seasoned Scripter)
|
2005-04-26 07:06 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
For me, the post #2 problem is a show stopper. It needs to be fixed/incorporated which means a major overhaul to the UDF's specifications.
|
Jose
|
(Seasoned Scripter)
|
2005-04-26 07:24 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Pardon my ignorance Jim, can you explain me the problem #2 with a sample for me to understand? I cannot find your reference.
|
Shawn
|
(KiX Supporter)
|
2005-04-26 07:32 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Me too - Can we have a summary of issues ?
|
jtokach
|
(Seasoned Scripter)
|
2005-04-26 07:35 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
The second post in this thread explains it. post #2
This format is standard and needs support. Given our setup, we have no facility to write or read that format.
|
Shawn
|
(KiX Supporter)
|
2005-04-26 07:44 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
So based on this link, we could create a Kixtart function called FormatXML(), is that where your heading ?
-Shawn
|
jtokach
|
(Seasoned Scripter)
|
2005-04-26 07:48 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Nope, we already have a formatXML function to format via XSL. What I'm saying is, try to create that XML from the current UDF's we have. It's not possible, b/c we have no way to reference the first <id> tag from the second, third or fourth.
|
Shawn
|
(KiX Supporter)
|
2005-04-26 07:53 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
If its not possible, then why worry about it ? ;0)
|
Jose
|
(Seasoned Scripter)
|
2005-04-26 07:54 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
I get your point, but that shoudnt be done with an Attribute like this <id number=1> FE to identify it like I posted above?. Code:
<korg> <users> <id n=1>1</id> <id n=2>2</id> <id n=3>3</id> <id n=4>4</id> <id n=5>5</id> </users> </korg>
BTW have you seen such format used that much?
|
jtokach
|
(Seasoned Scripter)
|
2005-04-26 08:19 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jose, that format is quite standard. I've seen it everywhere. In fact, it seems to be pretty dominant. There doesn't need to attributes is what my point is and many existing XML's may not have them so we need to address it. Example 1 at DevGuru
Example 2 (XML to SQL - This is my end goal)
|
Jose
|
(Seasoned Scripter)
|
2005-04-27 01:39 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
I see Jim, you are right about its importance but I am of the thought that there is plenty to do with what is done by now, sure we will get on with it. Dont you forget there is a community behind us ready to bring a solution after a particular need .
|
jtokach
|
(Seasoned Scripter)
|
2005-04-27 04:34 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jose, I'd love to start using these now, but I think once we get into it, the specifications will all change which will force you to go back to all of your old scripts and change them as well...
|
Jose
|
(Seasoned Scripter)
|
2005-04-30 03:10 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Well I guess there is gonna have to be some more fridge for them .
|
jtokach
|
(Seasoned Scripter)
|
2005-05-06 10:14 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jose, you win. I started looking into this, and let me tell you what a massive pain in the ass it is. I'm thinking that the attributes are going to be the way to go. We'll just need to claim "limited" XML support.
|
jtokach
|
(Seasoned Scripter)
|
2005-05-10 08:37 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Ok, pain in the ass or not, I couldn't find any way around this, so I spent some time and got it working.
Also note that I changed all of the function names so they all match up and can be sorted and searched on easier. Here's all of the latest code and an example that creates an XML file, parses it and writes some SQL based on it.
Code:
Break On $nul=SetOption("ASCII","On") $nul=SetOption("Explicit","On") $nul=SetOption("WrapAtEOL","On")
Dim $fileXMLdata Dim $xml, $
Dim $SQL,$iSQL,$uSQL,$DBServer,$DBName,$DBType,$DSN,$DBUsername,$DBPassword Dim $TableName,$PKey,$SKey,$FieldNames,$FieldData Dim $colXMLElements,$colE Dim $arySQL[0]
$fileXMLdata = "db.xml"
; Delete an existing XML file as the append functions will append to an ; existing file If Exist($fileXMLdata) Del $fileXMLdata EndIf
; Create the XML file using the new append functions $= XMLAppendElement($fileXMLdata, "Database", "") $= XMLAppendAttr($fileXMLdata, "Database", "Server", "MyServer") $= XMLAppendAttr($fileXMLdata, "Database", "Name", "MyDB") $= XMLAppendAttr($fileXMLdata, "Database", "Type", "MySQL") $= XMLAppendAttr($fileXMLdata, "Database", "Username", "root") $= XMLAppendAttr($fileXMLdata, "Database", "Password", "MyPass")
$= XMLAppendElement($fileXMLdata, "Database/Table", "") $= XMLAppendAttr($fileXMLdata, "Database/Table", "Name", "Computers") $= XMLAppendAttr($fileXMLdata, "Database/Table", "PrimaryKey", "Hostname") $= XMLAppendAttr($fileXMLdata, "Database/Table", "SecondaryKey", "")
$= XMLAppendElement($fileXMLdata, "Database/Table/Record", "") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hostname", "COMPUTER01") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/LastUpdated", @Date + " " + @Time) $= XMLAppendElement($fileXMLdata, "Database/Table/Record/HardwareMake", "Dell Computer Corporation") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/HardwareModel", "OptiPlex GX200") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/HardwareSN", "123572256132345") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/HardwareBiosVer", "DELL - 8|Phoenix ROM BIOS PLUS Version 1.10 A03|") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/HardwareBiosDate", "02/28/01") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/HardwareCPU", @CPU)
$= XMLAppendElement($fileXMLdata, "Database/Table", "") $= XMLAppendAttr($fileXMLdata, "Database/Table", "Name", "Hotfixes") $= XMLAppendAttr($fileXMLdata, "Database/Table", "PrimaryKey", "Hostname") $= XMLAppendAttr($fileXMLdata, "Database/Table", "SecondaryKey", "Hotfix")
$= XMLAppendElement($fileXMLdata, "Database/Table/Record", "") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hostname", "COMPUTER01") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/LastUpdated", @Date + " " + @Time) $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hotfix", "MS04_011")
$= XMLAppendElement($fileXMLdata, "Database/Table/Record", "") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hostname", "COMPUTER01") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/LastUpdated", @Date + " " + @Time) $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hotfix", "MS04_012")
$= XMLAppendElement($fileXMLdata, "Database/Table/Record", "") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hostname", "COMPUTER01") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/LastUpdated", @Date + " " + @Time) $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hotfix", "MS04_013")
$= XMLAppendElement($fileXMLdata, "Database/Table/Record", "") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hostname", "COMPUTER01") $= XMLAppendElement($fileXMLdata, "Database/Table/Record/LastUpdated", @Date + " " + @Time) $= XMLAppendElement($fileXMLdata, "Database/Table/Record/Hotfix", "MS04_014")
$xml = 0
; Enumerate all of the elements in the XML file into a collection of objects $colXMLElements = XMLEnumElements($fileXMLdata,"*")
; Iterate the collection, create SQL statments with the data, add each statement ; to an array For Each $colE In $colXMLElements Select Case $colE.TagName = "Database" $DBServer = $colE.getAttribute("Server") $DBName = $colE.getAttribute("Name") $DBType = $colE.getAttribute("Type") $DBUsername = $colE.getAttribute("Username") $DBPassword = $colE.getAttribute("Password") If $DBType = "MySQL" $DSN="DRIVER={MySQL ODBC 3.51 Driver};SERVER="+$DBServer+";DATABASE="+$DBName+";UID="+$DBUsername+";PWD="+$DBPassword EndIf
Case $colE.TagName = "Table" $TableName = $colE.getAttribute("Name") $PKey = $colE.getAttribute("PrimaryKey") $SKey = $colE.getAttribute("SecondaryKey")
Case $colE.TagName = "Record" If $FieldNames <> "" ;$uSQL = "UPDATE " + $TableName + " SET " + $element + " WHERE " + $KeyName + " = '" + $KeyData + "'" $iSQL = "INSERT INTO " + $TableName + "(" + $FieldNames + ") VALUES (" + $FieldData + ")" $arySQL[ubound($arySQL)]=$iSQL Redim Preserve $arySQL[ubound($arySQL)+1] EndIf $SQL = "" $FieldNames = "" $FieldData = "" Case 1 ; Must be a record for the current table. If $FieldNames = "" $FieldNames = $colE.TagName $FieldData = "'" + $colE.Text + "'" Else $FieldNames = $FieldNames + "," + $colE.TagName $FieldData = $FieldData + ",'" + $colE.Text + "'" EndIf EndSelect Next ; Adds the remaining parsed data to the array $iSQL = "INSERT INTO " + $TableName + "(" + $FieldNames + ") VALUES (" + $FieldData + ")" $arySQL[ubound($arySQL)]=$iSQL
; Print the data to the console ? "DSN: " + $DSN ? Dim $k For Each $k In $arySQL ? "iSQL: " + $k Next
Exit 1
Function XMLAppendAttr($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 = XMLLoad($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($SelectionTag.length-1) If @ERROR = "-2147352573" $ = XMLWriteValue($xml, $path, "") $SelectionTag = $xml.getElementsByTagName($Path) $AttrTag = $SelectionTag.item($SelectionTag.length-1) EndIf $write = $AttrTag.SetAttribute($Attr,$Value)
; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. $XMLWriteAttr = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object XMLSave($xml, $source) Else ; An XML string was passed. $XMLWriteAttr = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy EndFunction
; XMLAppendElement() - Writes a value to an XML element Function XMLAppendElement($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 ;? "filename" $xml = XMLLoad($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 ; The node does not exist $parentNode = $xml
for each $node in split($path,"/") Dim $colXMLElements $p = $p + $node
$colXMLElements = $xml.getElementsByTagName($p) If $colXMLElements.length > 1 $sectionNode = $colXMLElements.Item($colXMLElements.length-1) Else $sectionNode = $xml.SelectSingleNode($p) EndIf
if not $sectionNode $sectionNode = $xml.CreateElement($node) $parentNode = $parentNode.AppendChild($sectionNode) else $parentNode = $sectionNode endif $p = $p + "/" next Else Dim $colXMLElements Dim $aryNodes Dim $ParentNodeName ;? "Does exist, appending" ;The node does exist, get the count of each $aryNodes = split($path,"/") $Node = $aryNodes[ubound($aryNodes)] ;? "Node "$node $ParentNodeName = Join($aryNodes,"/",Ubound($aryNodes)) ;? "PN " $parentnodeName
$colXMLElements = $xml.getElementsByTagName($ParentNodeName) If $colXMLElements.length > 1 ;? "more than one" ;? "c " $colXMLElements.length ;? "item "$colXMLElements.Item($colXMLElements.length-1).TagName $ParentNode = $colXMLElements.Item($colXMLElements.length-1) ;$ParentNode = $xml.SelectSingleNode($parentnodeName) Else ;? "not more than one" ;$sectionNode = $xml.SelectSingleNode($parentnode) ;? "SN " $sectionNode.TagName $ParentNode = $xml.SelectSingleNode($parentnodeName) EndIf $sectionNode = $xml.CreateElement($node) $parentNode = $parentNode.AppendChild($sectionNode) EndIf
; wrtie val to current section If $sectionNode $sectionNode.Text = $value EndIf
; Begin Overloaded Var Exit Strategy If VarType($source) = 9 ; An object was passed. $XMLAppendElement = $xml Else If Instr($source,"<")=0 ;? "Save" ; A file name was passed, so we write it out and destory the object XMLSave($xml, $source) ;? "save2" Else ; An XML string was passed. $XMLAppendElement = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy
endfunction
; XMLCreateElement() - Creates an empty element pair Function XMLCreateElement($source,$path) $XMLCreateElement = XMLWriteValue($source,$path,"") EndFunction
; XMLEnumAttr() - Enums all attributes of an element Function XMLEnumAttr($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 = XMLLoad($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 $XMLEnumAttr = $colXMLElements.item(0).Attributes EndIf EndFunction
; XMLEnumElements() - Enums child elements of a given element Function XMLEnumElements($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 = XMLLoad($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 ; $XMLEnumElements = $xml.getElementsByTagName($path).Item(0) ; $XMLEnumElements = $XMLEnumElements.ChildNodes ; Case 1 ; $XMLEnumElements = $xml.getElementsByTagName($path) ;EndSelect $XMLEnumElements = $xml.getElementsByTagName($path) EndFunction
;XMLFormatOutput() - Formats the output style of an XMLDOM object to the standard Function XMLFormatOutput($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) $XMLFormatOutput = $objXMLDOM EndFunction
;XMLLoad() - Load an existing .XML file, instantiate XMLDOM object for use ;regardless of file existance. Function XMLLoad($filename) dim $, $rootNode, $objNewPI, $strType
$XMLLoad = CreateObject("Microsoft.XMLDOM") $XMLLoad.async = False $XMLLoad.preserverwhitespace = True
if not $XMLLoad return endif
$ = $XMLLoad.Load($filename) EndFunction
; XMLReadAttr() - Read a specific attribute of an XML element Function XMLReadAttr($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 = XMLLoad($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" $XMLReadAttr = "" Exit @Error Else $XMLReadAttr =$AttrName.getAttribute($Attr) EndIf
; Begin Overloaded Var Exit Strategy ; None needed ; End Overloaded Var Exit Strategy EndFunction
;XMLReadValue() - Reads the value of an XML element Function XMLReadValue($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 = XMLLoad($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 $XMLReadValue = $defaultValue Else $XMLReadValue = $sectionNode.FirstChild.Text EndIf EndFunction
; XMLRemoveAttr() - Deletes an XML element attribute Function XMLRemoveAttr($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 = XMLLoad($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. $XMLRemoveAttr = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object XMLSave($xml, $source) Else ; An XML string was passed. $XMLRemoveAttr = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy
EndFunction
; XMLRemoveElement() - Deletes an XML element (Recursively?) Function XMLRemoveElement($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 = XMLLoad($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. $XMLRemoveElement = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object XMLSave($xml, $source) Else ; An XML string was passed. $XMLRemoveElement = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy EndFunction
;XMLSave() - Saves an XMLDOM object to a file ; Requires: XMLFormatOutput() Function XMLSave($xml, $filename) $xml = XMLFormatOutput($xml) $XMLSave = $xml.Save($filename) EndFunction
Function XMLWriteAttr($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 = XMLLoad($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" $ = XMLWriteValue($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. $XMLWriteAttr = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object XMLSave($xml, $source) Else ; An XML string was passed. $XMLWriteAttr = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy EndFunction
; XMLWriteValue() - Writes a value to an XML element Function XMLWriteValue($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 = XMLLoad($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. $XMLWriteValue = $xml Else If Instr($source,"<")=0
; A file name was passed, so we write it out and destory the object XMLSave($xml, $source) Else ; An XML string was passed. $XMLWriteValue = $xml
EndIf EndIf ; End Overloaded Var Exit Strategy
endfunction
; ****************************************************************************** ; XMLApplyXSL() - Applies an XSL template. (Much potential here for an expanded ; set, see http://www.devguru.com/Technologies/xslt/quickref/xslt_index.html Function XMLApplyXSL()
EndFunction
; XMLApplyXSLFilter() - Apply a filter to an XMLDOM object. (Search the db. XSL related.) Function XMLApplyXSLFilter()
EndFunction
Function XMLEnum($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 $XMLEnum = $NodeList EndFunction
|
Jose
|
(Seasoned Scripter)
|
2005-05-12 06:28 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Intresting concept man!.
Jim I have tryed your code but I get an error here in XMLFormatOutput($objXMLDOM) at this point. Code:
$strXSL = " chr(34) + "UTF-8" + chr(34) + "?>" + @CRLF
Replaced with this and worked out. Code:
$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>"
Check it Jim please.
|
jtokach
|
(Seasoned Scripter)
|
2005-05-12 04:45 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jose, this crappy board upgrade keeps dropping XML tags... I'll update the previous code and if there are no further items to work on, I think we're ready to package these up for the UDF forum.
|
jtokach
|
(Seasoned Scripter)
|
2005-05-12 04:51 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Regarding the missing code, the trick is to: 1. make the orignal post 2. notice missing XML/HTML tags 3. edit the post, you'll see that the code is actually there 4. save the post again and voila, it magically appears
This is a bug, which is currently working to our advantage. One of the MODS should report to Henri and/or Infopop.
Anyway, the code should work now.
|
NTDOC
|
(KiX Master)
|
2005-05-26 10:45 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Just FYI if interested - not really of much help internally though with KiXtart.
Improve XML Processing with VTD-XML
|
NTDOC
|
(KiX Master)
|
2005-06-05 12:36 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Jim,
Just ran across this in the WMI materials. Here is an example. Shawn has a mini reader that read the output just fine. Not solid code, but example works.
SWbemObjectEx.GetText_ The GetText_ method of the SWbemObjectEx object returns an XML representation of an object or instance. The text file is formatted in the XML format specified as shown in WbemObjectTextFormatEnum.
WbemObjectTextFormatEnum
Code:
Break On Dim $SO,$Pause $SO=SetOption('Explicit','On') $SO=SetOption('NoVarsInStrings','On') $SO=SetOption('WrapAtEOL','Off') Dim $MyBIOSInfo,$W $MyBIOSInfo = GetBIOSInfo() If Exist('C:\TEMP\TEST.XML') DEL 'C:\TEMP\TEST.XML' EndIf $W = Open(1, 'C:\TEMP\TEST.XML',5) $W = WriteLine(1,$MyBIOSInfo[0]+@CRLF) $W = Close(1) Function GetBIOSInfo() Dim $Computer, $WMIService, $BIOSItems Dim $Item, $SerialNumber, $Manufacturer, $BIOSArray[1] Dim $XMLDtd $XMLDtd = 2 $Computer = "." $WMIService = GetObject("winmgmts:\\" + $Computer + "\root\cimv2") $BIOSItems = $WMIService.ExecQuery("Select * from Win32_BIOS",,48) For Each $Item in $BIOSItems $SerialNumber = $Item.GetText_($XMLDtd) Next $BIOSArray[0]=$SerialNumber $GetBIOSInfo=$BIOSArray EndFunction
|
jtokach
|
(Seasoned Scripter)
|
2005-06-10 08:08 PM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
This is interesting. I can't wait to get a chance to play with it.
|
NTDOC
|
(KiX Master)
|
2006-02-27 09:17 AM
|
|
|
|
|
Re: RFC: XML UDF's
|
|
Not sure if you've seen this or not as I've not reviewed all the code you've written so far.
How to navigate XML with the XPathNavigator class by using Visual Basic http://support.microsoft.com/kb/301111/en-us
|