I'm using classic ASP in my project. I want to merge two XMLs together. How do I do this? Below is my sample code:
XML 1
<CATALOG>
<CD>
<TITLE>1</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>2</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>3</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
</CATALOG>
XML2
<CATALOG>
<CD>
<TITLE>4</TITLE>
<ARTIST>Gary Moore</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>Virgin records</COMPANY>
<PRICE>10.20</PRICE>
<YEAR>1990</YEAR>
</CD>
<CD>
<TITLE>5</TITLE>
<ARTIST>Eros Ramazzotti</ARTIST>
<COUNTRY>EU</COUNTRY>
<COMPANY>BMG</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1997</YEAR>
</CD>
<CD>
<TITLE>6</TITLE>
<ARTIST>Bee Gees</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>Polydor</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1998</YEAR>
</CD>
</CATALOG>
This is ASP code I currently use:
Dim doc1 ''# As MSXML2.DOMDocument30
Dim doc2 ''# As MSXML2.DOMDocument30
Dim doc2Node ''# As MSXML2.IXMLDOMNode
Set doc1 = createobject("MSXML2.DOMDocument.3.0")
Set doc2 = createobject("MSXML2.DOMDocument.3.0")
doc1.Load "01.xml"
doc2.Load "02.xml"
For Each doc2Node In doc2.documentElement.childNodes
doc1.documentElement.appendChild doc2Node
Next
response.write doc1.xml
But now I'm getting an error:
Microsoft VBScript runtime error '800a01a8'
Object required: 'documentElement'
Expanding on Jørn Schou-Rode's answer:
<%
Dim doc1 'As MSXML2.DOMDocument30
Dim doc2 'As MSXML2.DOMDocument30
Dim doc2Node 'As MSXML2.IXMLDOMNode
Set doc1 = createobject("MSXML2.DOMDocument.3.0")
Set doc2 = createobject("MSXML2.DOMDocument.3.0")
doc1.Load "01.xml"
doc2.Load "02.xml"
Response.Write ( doc1.xml.Replace("</CATALOG>", doc2.xml.Replace( "<?xml version="1.0" encoding="ISO-8859-1" ?>","").Replace("<CATALOG>","") )
%>
This would replace the tag from doc1.xml with the doc2.xml without the first two lines, but again, would only work for this situation where you have these two xml files and they don't contain duplicate nodes.
You could read the files in using the FileSystemObject which would be faster, but the benefit of loading it in the DOM is that it would only load well formed xml.
Your basic approach should work. I suspect one of your documents does not load correctly because it is not well-formed or has an encoding error. Please check what this modification gives you:
Set doc1 = LoadXml("01.xml", True)
Set doc2 = LoadXml("02.xml", True)
''# ... all the rest of your stuff ...
Function LoadXml(XmlPath, FailOnError)
Dim xml, e
Set xml = Server.CreateObject("MSXML2.DOMDocument.3.0")
xml.Load XmlPath
Set e = xml.parseError
If e.errorCode <> 0 Then
DebugPrint "XML parsing error " & e.errorCode
DebugPrint "in file " & e.url
DebugPrint "on line: " & e.line & ", pos: " & e.linePos
DebugPrint "reason: " & e.reason
DebugPrint "source: " & e.srcText
If FailOnError Then Response.End
End If
Set LoadXml = xml
End Function
Sub DebugPrint(s)
Response.Write Server.HTMLEncode(s) & "<br>"
End Sub
Disclaimer: This answer contains a "ghetto" solution to the problem in question. While it should work just fine for this particular problem, it will not solve any XML related problem.
Considering that you need simply need to concatenate the nodes right below the document node in the two documents, it should be trivial to solve the question using simple string manipulation, without parsing the actual XML. Just to get the idea:
- Read all lines except the last one from
01.xml
, and write them to your output stream.
- Read all lines except the first two from
02.xml
, and write them to your output stream.
My VBScript is pretty rusty, but I believe something like this should cut it:
Const ForReading = 1
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set textStream = objFSO.OpenTextFile(Server.MapPath("01.xml"), ForReading)
lastLine = ""
Do While Not textStream.AtEndOfStream
Response.Write lastLine
lastLine = TextStream.readline
Loop
Set textStream = objFSO.OpenTextFile(Server.MapPath("02.xml"), ForReading)
counter = 0
Do While Not textStream.AtEndOfStream
counter = counter + 1
If counter > 2 Then
Response.Write TextStream.readline
End If
Loop