Avatar billede carstenandersen Nybegynder
12. januar 2011 - 13:28 Der er 16 kommentarer og
1 løsning

Parse XML - derefter til database

Hej eksperter

Jeg er ved at forsøge at få læst en xml-fil, og efterfølgende lægge oplysningerne ind i en database. Jeg har undersøgt flere muligheder, men mangler lige overblikket over den bedste måde at gøre det ;-)

Har f.eks. leget med:

<script type="text/javascript">
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.open("GET","1.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;

txt=xmlDoc.getElementsByTagName("GridImage/Url")[0].childNodes[0].nodeValue;
txt2=xmlDoc.getElementsByTagName("Price")[0].childNodes[0].nodeValue;
document.write(txt);
document.write(txt2);
</script>

hvor jeg fint får udskrevet indholdet af txt og txt2, men hvordan får jeg indholdet fra txt og txt "ud af java-scriptet", så jeg kan bruge det ved indsættelse i database? Ovenstående er formentligt ikke den bedste måde, da xml-dokumentet jo skal loopes.

På forhånd tak.
Avatar billede softspot Forsker
12. januar 2011 - 13:39 #1
Er det meningen at du vil køre det i browseren på klienten, eller er det rent faktisk noget der skal køres på serveren?
Avatar billede carstenandersen Nybegynder
12. januar 2011 - 14:31 #2
Ingen brugere skal se det - blot for at få data fra xml-fil til database. Det er derfor lige meget, hvor det køres - blot hvor det er smartest og nemmest at gøre det.
Avatar billede softspot Forsker
12. januar 2011 - 14:49 #3
Det er umiddelbart mest naturligt at udføre dette på serveren, da dette typisk er nærmere databasen end klienten.

Skal du gøre dette i ASP med VBScript, kunne det se nogenlunde således ud:

filnavn = "1.xml"
set doc = Server.CreateObject("MSXML2.DOMDocument")
call doc.load(Server.MapPath(filnavn))
txt = doc.documentElement.selectSingleNode("GridImage/Url[0]/*[0]").nodeValue
txt2 = doc.documentElement.selectSingleNode("Price[0]/*[0]").nodeValue

Det er ganske utestet, men princippet er som vist.

Du kan herefter bruge txt og txt2 til at lægge i databasen...
Avatar billede carstenandersen Nybegynder
12. januar 2011 - 15:03 #4
Spændende :-)

Den fejler dog med:

Microsoft VBScript runtime error '800a01a8'

Object required: 'doc.documentElement.selectSingleNode(...)'

/1parse2.asp, line 5

Linie 5 er: txt = ....

Xml-filen indeholder flere produkter, så hvordan kan jeg indflette et array eller løkke?
Avatar billede softspot Forsker
12. januar 2011 - 15:09 #5
Fejlen opstår givetvis pga. at den angivne XPath ikke returnerer noget element og referencen til nodeValue derfor ikke er gyldig (nodeValue er naturligvis ikke defineret på værdien nothing :-)).

Kan du evt. vise et repræsentativt udsnit af din XML?
Avatar billede carstenandersen Nybegynder
12. januar 2011 - 15:15 #6
Kommer lige her ;-)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProductSearch>
    <Products firstResultPosition="1" totalResultsAvailable="203" totalResultsReturned="10">
        <Product type="Offer">
            <Offer id="5930be7c929f7150c3cff677e92be310">
                <Url>xxxxxx</Url>
                <ProductName>Danmark : Blokhus</ProductName>
                <Price currency="dkk">8195.00</Price>
                <ListImage>
                    <Url>xxxUrl>
                    <Height>90</Height>
                    <Width>90</Width>
                </ListImage>
                <GridImage>
                    <Url>xxxUrl>
                    <Height>90</Height>
                    <Width>90</Width>
                </GridImage>
                <Summary>7 naetter, 9 voksne, 0 boern.                  2 dobbeltsenge og 3 enkeltsenge.</Summary>
                <Merchant id="5642523">
                    <Name>xxx</Name>
                </Merchant>
                <Category id="170201">
                    <Name>Ferie- &amp; Sommerhuse</Name>
                </Category>
            </Offer>
        </Product>
Avatar billede softspot Forsker
12. januar 2011 - 15:28 #7
Jeg kan ikke helt forstå din indeksering i det oprindelige eksempel, men jeg ville da foreslå flg. i stedet:

filnavn = "1.xml"
set doc = Server.CreateObject("MSXML2.DOMDocument")
call doc.load(Server.MapPath(filnavn))
txt = doc.documentElement.selectSingleNode("//GridImage/Url").nodeValue
txt2 = doc.documentElement.selectSingleNode("//Price").nodeValue

Mht. det at du skal have trukket flere ud, så skal jeg lige vide hvordan det skal fungere ifht. at data skal databasen...?
Avatar billede carstenandersen Nybegynder
12. januar 2011 - 15:38 #8
Min første indeksering var blot taget fra et helt andet eksempel. Har prøvet dit forslag - fejler ikke, men udskriver heller ikke værdien af txt og txt2 ved:

<%

filnavn = "1.xml"
set doc = Server.CreateObject("MSXML2.DOMDocument")
call doc.load(Server.MapPath(filnavn))
txt = doc.documentElement.selectSingleNode("//GridImage/Url").nodeValue
txt2 = doc.documentElement.selectSingleNode("//Price").nodeValue

%>

<% Response.Write txt %>
<br>
<% Response.Write txt2 %>

I forhold til database, så hver gang et produkt er gennemløbet i XML, skal det lægges i databasen, hvorefter løkken fortsætter. Nok info?
Avatar billede softspot Forsker
12. januar 2011 - 15:46 #9
Prøv at udskifte .nodeValue med .text i stedet...
Avatar billede carstenandersen Nybegynder
12. januar 2011 - 16:06 #10
Sådan, det virker :-)

Hvis du kan klare det med løkken og databasen, vil det bare være perfekt - giver gerne flere point.

Bliver desværre nødsaget til at lukke nu, men logger på igen senere.
Avatar billede softspot Forsker
12. januar 2011 - 17:19 #11
Du kan tage udgangspunkt i nedenstående:

filnavn = "1.xml"
set doc = Server.CreateObject("MSXML2.DOMDocument")
call doc.load(Server.MapPath(filnavn))
set offers = doc.documentElement.selectNodes("//Offer")

' forbered SQL og Command-objekt til at skrive i databasen
sql = "INSERT INTO tabel(txt,txt2) VALUES(?,?)"
set cmd = Server.CreateObject("ADODB.Command")
cmd.CommandText = sql
cmd.CommandType = adCmdText
set cmd.ActiveConnection = conn  ' conn er din connection til db

' gennemløb de fundne data
for each offer in offers
  ' hent data fra de relevante felter i XML'en
  txt = offer.selectSingleNode("GridImage/Url").text
  txt2 = offer.selectNodes("Price").text

  ' skriv til databasen...
  cmd.Execute , array(txt,txt2)
next

Jeg benytter et forberedt Command-objekt og parameteriserede opdateringsforespørgsler i databasen, for at undgå evt. injectionsforsøg via XML'en.

SQL-sætningen skal naturligvis tilpasses din databasestruktur, men princippet er vist til at finde ud af... :-)
Avatar billede carstenandersen Nybegynder
12. januar 2011 - 23:00 #12
Dette Command-objekt var lidt for spændende, men lykkedes alligevel ud fra din kode at lave:

<%
Server.ScriptTimeout = 1440

filnavn = "1.xml"
set doc = Server.CreateObject("MSXML2.DOMDocument")
call doc.load(Server.MapPath(filnavn))
set offers = doc.documentElement.selectNodes("//Offer")

' gennemløb de fundne data
for each offer in offers
  ' hent data fra de relevante felter i XML'en
  Offerid = offer.selectSingleNode("Category/Name").text
  Url = offer.selectSingleNode("GridImage/Url").text
  Pris = offer.selectSingleNode("Price").text

  ' skriv til databasen...

  SQL14 = "INSERT INTO Rejsetilbud(Offerid, Url, Pris)"
  SQL14 = SQL14 & "Values("
    SQL14 = SQL14 & "'" & Offerid & "',"
    SQL14 = SQL14 & "'" & Url & "',"
    SQL14 = SQL14 & "'" & Pris & "'"
    SQL14 = SQL14 & ")"
   
    Set RS14 = conn.execute(SQL14)
next
%>

Et lille spørgsmål. Hvordan udtrækker jeg værdien af id i Merchant <Merchant id="5642523">?

Ellers et stort tak for hjælpen. Smid et svar og pointene er dine.
Avatar billede softspot Forsker
12. januar 2011 - 23:33 #13
Du kan hente en atribut med funktionen getAttribute således:

MerchantId = offer.selectSingleNode("Merchant").getAttribute("id")

Hvad var problemet med Command-objektet? Du har givetvis problemer med konstanten adCmdText, men ellers burde det fungere uden yderligere afhængigheder. Du kan benytte den konstante værdi i stedet for adCmdText. Så skal du bare skrive således i stedet:

cmd.CommandType = 1

Du kan se de mulige konstanter (og mere om ADO) her: http://msdn.microsoft.com/en-us/library/ms675946(v=VS.85).aspx

Jeg vil helt klart anbefale at du kigger meget mere på Command-objektet, da det i stor udstrækning kan sikre din webapplikation mod SQL-injections (hvilket den gængse strengsammensætningsmetode ikke kan siges at gøre - tvært imod :O). Derud over bliver dine SQL-sætninger og koden meget lettere at læse for dig og andre...
Avatar billede softspot Forsker
12. januar 2011 - 23:35 #14
Tag evt. et kig på min guide her på eksperten: http://www.eksperten.dk/guide/1250, der går lidt mere i dybden mht. opsætning omkring - og brug af Command-objektet til at sikre sig mod SQL-injections.
Avatar billede carstenandersen Nybegynder
13. januar 2011 - 06:32 #15
Command-objektet virkede lidt uoverskueligt, da det var helt nyt for mig, hvorfor jeg prøvede den gamle metode. Jeg kan godt se din pointe, og vil helt klart arbejde videre i den retning :-)

Lige et lille afslutningsspg. Den kører en løkke på Offer, men hvordan kan jeg også lige få Offer id med ind i min database, altså værdien af <Offer id="xxxxxxxx">?

Du har været en helt kanon hjælp, så jeg har oprettet et spg. med yderligere 100 point - du har fortjent dem og endnu engang en stor tak for hjælpen. http://www.eksperten.dk/spm/928780
Avatar billede softspot Forsker
13. januar 2011 - 08:48 #16
Du henter offerid på samme måde som merchantid, nemlig med getAttribute:

OfferId = offer.getAttribute("id")

Det er en klog beslutning af kaste sin energi efter en mere sikker måde at kode sine hjemmesider på (der er nok af muligheder for at lave sikkerhedshuller, så det er bare med at lukke dem man nemt kan komme afsted med at lukke :-))

Mht. dit ekstra spørgsmål til pointgivning, så takker jeg mange gange for den venlige tanke, men det er ikke lovligt at give mere end 200 point pr. spørgsmål (og heller ikke nødvendigt), så det ekstra spørgsmål du har oprettet bør du blot selv svare på og tage pointene tilbage. Husk blot at få accepteret svaret på denne tråd, så er det fint. Men endnu engang tak for den venlige gestus :-)
Avatar billede carstenandersen Nybegynder
13. januar 2011 - 10:53 #17
Sådan, det virker perfekt :-)

Du har virkelig været til stor hjælp - tak for det !

Jeg lukker det andet spg. - det med de 200 point var jeg ikke lige obs på ;-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester