How to merge two XML files in classic ASP?

2019-06-24 02:20发布

问题:

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'

回答1:

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.



回答2:

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


回答3:

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:

  1. Read all lines except the last one from 01.xml, and write them to your output stream.
  2. 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