[Closed] XML writing
When I try to run this code:
(
Address = "C:/MyTest.xml"
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
EmailEle=XmlDoc.createElement "MyEmail@google.com"
DocEle.appendChild EmailEle
XmlDoc.save Address
)
This error comes up:
-- Runtime error: dotNet runtime exception: The '@' character, hexadecimal value 0x40, cannot be included in a name.
I don’t know what “hexadecimal value 0x40” is and how I can use “@” in xml nodes name.
0x40 is ASCII code of @ symbol
you can not use @ symbol in xml node or attribute name. but can use it in values.
I changed code to store data in a Attribute, its work.
But it seems searching and finding a attribute value is slower than getting a node by name.
(
--creating document
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
for i=1 to 200 do
(
NodeName = "MyNode"+(i as string)
EmailEle=XmlDoc.createElement NodeName
EmailEle.setattribute "Name" NodeName
DocEle.appendChild EmailEle
)
FindNodeName = "MyNode100"
--find by name:
start = timeStamp()
DocEle.item[FindNodeName]
end = timeStamp()
format "Find by name took % seconds
" ((end - start) / 1000.0)
--find by attribute:
start = timeStamp()
(for i=0 to DocEle.childnodes.count-1 where (Nd = DocEle.childnodes.itemof[i]).getattribute "Name"==FindNodeName collect Nd)[1]
end = timeStamp()
format "Find by attribute took % seconds
" ((end - start) / 1000.0)
)
slower. but you can make a node name just replacing the @ symbol with any other string… like “here_is_the_at_sign”
My problem is that string comes from user input(Textbox).
Another question is which method is faster to find a node by attribute:
(
--creating document
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
for i=1 to 1000 do
(
NodeName = "MyNode"+(i as string)
EmailEle=XmlDoc.createElement NodeName
EmailEle.setattribute "Name" NodeName
DocEle.appendChild EmailEle
)
FindNodeName = "MyNode100"
--find by attribute(Collect):
start = timeStamp()
Childes = DocEle.childnodes
(for i=0 to Childes.count-1 where (Nd = Childes.itemof[i]).getattribute "Name"==FindNodeName collect Nd)[1]
end = timeStamp()
format "Find by attribute(Collect) took % seconds
" ((end - start) / 1000.0)
--find by attribute(While):
start = timeStamp()
notFound = true
Childes = DocEle.childnodes
for i=0 to Childes.count-1 while notFound=true do
(
if (Nd = Childes.itemof[i]).getattribute "Name"==FindNodeName do
(
notFound = false
Nd
)
)
end = timeStamp()
format "Find by attribute(While) took % seconds
" ((end - start) / 1000.0)
)
I’m bit confused about xpath.
Please, Correct my code if is not true:
(
--creating document
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
SubNode=XmlDoc.createElement "SubNode"
DocEle.appendChild SubNode
for i=1 to 10 do
(
Nd = XmlDoc.createElement ("Nd"+(i as string))
Nd.setattribute "Name" ("AttVal"+(i as string))
SubNode.appendChild Nd
)
-- XmlDoc.save "C:/MyTest.xml"
--find by XPath:
Nd = SubNode.SelectSingleNode("./*[@Name= 'AttVal3']")
)
xpath is very powerful but like regex very “syntax rich”. I’ve learned a lot from this site and also wrote a small article about it.
Very useful article and tutorials, Thank you!
In my case, I want to find child node of specific node by using its attribute.we don’t know its parents xpath.
Getting a node by its attribute with xpath looks like this: //title[@lang=‘eng’]. this will select the title node wherever it is in the xml but only if it has an attribute “lang” with the value “eng”.
If you want all childnodes of that node you’d use: //title[@lang=‘eng’]/*, or if you want a specific childnode called “somename”, you’d use //title[@lang=‘eng’]/somename.
I always keep that site from w3schools open when I work with xpath.
Your example are great, But maybe I missing something, I’m trying to mimic get single child item by name:
MyNode.item[ItemName] >>> MyNode.item[Attribute]
Well,
if you want even more specific help I’d really need to see the xml you’re working with. Otherwise just look at the w3schools website and figure it out by trial and error. That’s most sustainable anyway.
This code shows what I want:
(
--creating document
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
GroupNd=XmlDoc.createElement "Group"
DocEle.appendChild GroupNd
for i=1 to 10 do
(
Nd = XmlDoc.createElement "Nd"
Nd.setattribute "Name" ("Name_"+(i as string))
GroupNd.appendChild Nd
)
XmlDoc.save "C:/MyTest.xml"
--How I can get a child of GroupNd with Attribute:(Name == "Name_5")?
)
How I can get a child of GroupNd with Attribute:(Name == “Name_5”) ?
it’s
a = xmldoc.selectsinglenode "//*[@Name='Name_5']"
which translating from XPath means: find the first node starting from root, with any name but with attribute “Name” which equals “Name_5”
Darn it, too slow.
If you want to be specific and only want children of Group/Nd with that specific attribute, you’d use
xmlDoc = dotNetObject "system.xml.xmlDocument"
xmlDoc.load "somePath"
xmlDoc.selectSingleNode "//Group/Nd[@Name='Name_5']"
And what about two group with same structure? How we can get node from second group?
(
--creating document
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
for i=1 to 2 do
(
GroupNd=XmlDoc.createElement "Group"
DocEle.appendChild GroupNd
for i=1 to 10 do
(
Nd = XmlDoc.createElement "Nd"
Nd.setattribute "Name" ("Name_"+(i as string))
GroupNd.appendChild Nd
)
)
XmlDoc.save "C:/MyTest.xml"
)
And what about two group with same structure? How we can get node from second group?
(
--creating document
XmlDoc=dotNetObject "System.xml.xmlDocument"
DocEle=XmlDoc.createElement "DocEle"
XmlDoc.appendChild DocEle
for i=1 to 2 do
(
GroupNd=XmlDoc.createElement "Group"
DocEle.appendChild GroupNd
for i=1 to 10 do
(
Nd = XmlDoc.createElement "Nd"
Nd.setattribute "Name" ("Name_"+(i as string))
GroupNd.appendChild Nd
)
)
XmlDoc.save "C:/MyTest.xml"
)