- We need to update
<title>text, where the<id>is 11 to another text. - without knowing in which position the row
<myrow>is. Here are the rules for this, i need to use one of these connections listed below, since the Server only support those:
Set objXML = Server.CreateObject("Microsoft.XMLDOM") Set objXML = Server.CreateObject("MSXML2.FreeThreadedDOMDocument") Set objXML = Server.CreateObject("MSXML2.DOMDocument") Set objXML = Server.CreateObject("MSXML2.DOMDocument.3.0") Set objXML = Server.CreateObject("MSXML2.DOMDocument.6.0")Here it's the XML:
<?xml version="1.0" encoding="iso-8859-2" ?> <xmldata> <myrow> <id>10</id> <title>title1</title> <msg>Hello world!</msg> </myrow> <myrow> <id>11</id> <title>title2</title> <msg>Hello world!</msg> </myrow> <myrow> <id>12</id> <title>title3</title> <msg>Hello world!</msg> </myrow> </xmldata>Here it's the ASP VBScript code that we have at the moment:
sub xmlUpdate(xpth) Set xmlObj = Server.CreateObject("Microsoft.XMLDOM") xmlObj.async = False xmlObj.setProperty "ServerHTTPRequest", True xmlObj.Load(xpth) If xmlObj.parseError.errorCode <> 0 Then Response.Write "Error Reading File - " & xmlObj.parseError.reason & "<p>" End If '---we need the rest of the code bellow------------------------- '--------------------------------------------------------------- xmlObj.save(xpth) end subNote: I already have a code that updates the first row, but is not good when we do not know where the row is.
3 Answers
Your
- question implies two nodes, one to change and one to base the change on; but I can't relate that to your specs ('to another text')
- sample .xml is not well-formed (non-closed myrows)
- code uses spurious () (.load, .save)
- attempt to .save even when .load fails makes no sense
To find the node to change, use an XPath looking for a xmldata having a myrow having an id of "11". You can adapt that strategy to find another node wrt which you want to compute the new title. Then find that node's title sibling via its parent and change the .text. In code:
Dim sXPath : sXPath = "/xmldata/myrow/id[. = ""11""]"
Dim nd11 : Set nd11 = xmlObj.selectSingleNode(sXPath)
If nd11 Is Nothing Then
WScript.Echo "failed:", sXPath
Else
Dim ndTitle : Set ndTitle = nd11.parentNode.selectSingleNode("title")
WScript.Echo "found:", nd11.tagName, nd11.text, ndTitle.text
ndTitle.text = "pipapo"
WScript.Echo "changed:", nd11.parentNode.xml
End If
output (simple script, not ASP):
cscript 27749208.vbs
found: id 11 title2
changed: <myrow>
<id>11</id>
<title>pipapo</title>
<msg>Hello world!</msg>
</myrow>
Food for thought for efficiency aficionados:
A way is correct, if it gives correct results reliably. Some correct ways may be more efficient than others. The efficiency of ways that fail under realistic conditions need not be discussed.
The above strategy will succeed (without any change) if the myrow element looks like
changed: <myrow>
<title>pipapo</title>
<id>
11
</id>
<msg>Hello world!</msg>
</myrow>
InStr() for "<id>11</id>" will fail. You may tinker with a RegExp, but then there will be no title 'beyond that'. Feel free to do some magic with InStrRev() or InStr() on Mid(). But then please show reliably working code of less then about 10 lines. Make sure it handles initially empty title tags (either "<title/>" or "<title></title>") correctly.
What if the next version of the file contains
<mycol><id>11</id><title/></mycol>
This sample uses iso-8859-2 encoding. The standard encoding for XML is UTF-8. For that you'd need code to load and save the file using an ADODB.Stream. Try to do that 'more efficiently' as by using .load and .save.
1 Comment
- I see that you search a solution for (ASP/VBScript).
- even if the solution for (wscript/VBScript) looks similar since the language is the same, you will need some changes to make it work.
- and yes, it will work with those connections you wrote in your comment.
- Based on @Ekkehard's idea, I wrote an entire solution that will work with ASP-Classic (already tested).
Call test(server.mappatch("/myfolder/myxmlfile.xml"))
sub test(xpth)
dim xmlObj,sxPth,ndRef,ndTarget,mytext,myReference,myTarget
myReference="11" : myTarget="title" : mytext="some text"
Set xmlObj = Server.CreateObject("Microsoft.XMLDOM")
xmlObj.async = False
xmlObj.setProperty "ServerHTTPRequest", True
xmlObj.Load(xpth)
If xmlObj.parseError.errorCode <> 0 Then
Response.Write "Error Reading File - " & xmlObj.parseError.reason & "<p>"
End If
sxPth = "/xmldata/myrow/id[. = """&myReference&"""]"
Set ndRef = xmlObj.selectSingleNode(sxPth)
If ndRef Is Nothing Then
response.write "Not found:"& " " &sxPth& "<br />"
Else
Set ndTarget = ndRef.parentNode.selectSingleNode(myTarget)
response.write "found reference:["& " " &ndRef.tagName& "][" &ndRef.text& "] <br /> target:[" &ndTarget.text& "]"
ndTarget.text = mytext
response.write " changed to:[" & myText & "] <br />"
End If
xmlObj.save(xpth)
end sub
Comments
Read the entire XML as a string. Search in the string for "<id>11</id>". If found, search for "<title>" beyond that, search for "</title>" beyond that, substitute text in the string, then use that as the new XML. Sometimes it's much easier to not parse the XML.