Avatar billede renewester Nybegynder
19. august 2005 - 09:08 Der er 8 kommentarer og
1 løsning

Hent værdier enkeltvist fra XML-fil

Hej

Jeg er lige startet med at eksperimentere med XML, og vil prøve at indlæse en simpel XML-fil for at gemme værdierne i en database.

Min kode ser sådan ud:

Set objXML = Server.CreateObject("Microsoft.XMLDOM")
objXML.async = False
objXML.Load strPath

Set objRootElement = objXML.documentElement

For i = 0 to objRootElement.childNodes.Length - 1                   
    response.Write objRootElement.childNodes.item(i).Text & "<br>"
    response.Write objRootElement.childNodes.item(i).NodeName & "<br>"
Next
                   
Set objXML = nothing


Filen ser sådan ud:
<?xml version="1.0"?>
<ROOT>
<khoved>
<khoved_id>10029</khoved_id>
<khoved_navn>Den individuelle udviklingsplan</khoved_navn>
<khoved_prisprdeltager>290</khoved_prisprdeltager>
</khoved>
<khoved>
<khoved_id>10030</khoved_id>
<khoved_navn>YYY1</khoved_navn>
<khoved_prisprdeltager>120</khoved_prisprdeltager>
</khoved>
<khoved>
<khoved_id>10031</khoved_id>
<khoved_navn>BudgTest</khoved_navn>
<khoved_prisprdeltager>55</khoved_prisprdeltager>
</khoved>
</ROOT>

Når jeg prøver at skrive outputtet ud, så ser det sådan ud:
10029 Den individuelle udviklingsplan 2900
khoved
10030 YYY1 1200
khoved
10031 BudgTest 550
khoved

Jeg har behov for at få fat i de 3 elementer enkeltvist, så jeg derved kan gemme det i databasen, men jeg kan kun få dem vist i én streng (.text).

For en XML-haj er dette sikkert et helt banalt spørgsmål, men jeg skal jo lige i gang ;-)

Er der en der har en idé?
Avatar billede renewester Nybegynder
19. august 2005 - 09:09 #1
Sorry, outputtet til skærmen ser sådan ud:

Når jeg prøver at skrive outputtet ud, så ser det sådan ud:
10029 Den individuelle udviklingsplan 290
khoved
10030 YYY1 120
khoved
10031 BudgTest 55
khoved
Avatar billede softspot Forsker
19. august 2005 - 11:16 #2
Det er fordi .Text viser hele indholdet af en node (inklusiv undernoders tekst). Du skal benytte nodeValue i stedet, så burde du få selve nodens tekst uden undernoder.

Tip: Jeg vil varmt anbefale at du kaster dig over XPath, da det superlækkert at finde data med i en XML-fil. XPath kan bla. benyttes i samspil med funktionerne selectSingleNode (som finder en enkelt node) og selectNodes (som finder en mængde noder). XPath er kort fortalt XML'ens SQL-sprog, dvs. til at lave forspørgsler i en XML-struktur.

Du kan f.eks. finde alle khoved-noder der ligger under ROOT ved at skrive:

objRootElement.selectNodes("/ROOT/khoved")

eller alle khoved-noder hvor khoved_id = 10030 ved at skrive:

objRootElement.selectNodes("/ROOT/khoved[khoved_id='10030']")

Hvis du kun vil finde den første forkomst af en node, kan du som nævnt benytte:

objRootElement.selectSingleNode("/ROOT/khoved[khoved_id='10030']")

Hvis du vil finde alle beskrivelse-noder som indeholder en deltekst kan du benytte:

objRootElement.selectNodes("//beskrivelse[text()=contains('XPath rykker')]")

Som du måske kan se, så er det rigtig mange muligheder med XPath, det er bare et spørgsmål om at have idéerne til hvad man vil... :)
Avatar billede renewester Nybegynder
20. august 2005 - 21:06 #3
Hej softspot
Tak for dit svar :-)

Jeg har eksperimenteret lidt med din råd, men det giver mig desværre ikke de værdier jeg har behov for.

Jeg har behov for <element> og <værdi>.
F.eks.:

"khoved_id" og "10029"
"khoved_navn" og "Den individuelle udviklingsplan"
"khoved_prisprdeltager" og "290"

Dette for hver eneste "khoved"-element.
NodeValue giver mig bare en tom linie, og objRootElement.selectNodes("/ROOT/khoved") giver mig følgende fejl: "Antallet af argumenter er forkert eller egenskabstildelingen er ugyldig"

Kan du evt. se hvad jeg skal tilrette i mit FOR-LOOP for at få de ønskede værdier ud, så jeg kan gemme dem i en database?
Avatar billede softspot Forsker
20. august 2005 - 21:28 #4
Hmm... jeg har lige kigget lidt på en konkret test af noget kode og det lader til at jeg ikke forstår dokumentationen mht. nodeValue. Det er der dog råd for, for jeg kan stadig bruge text-egenskaben på leaf-noder til at hente tekst ud af en node. Det betyder at jeg kan finde de værdier du efterspørger på flg. måde:

dim objXml, objRoot
dim strPath

strPath = Server.MapPath("testXml.xml")

set objXml = Server.CreateObject("Microsoft.XMLDOM")
objXml.Load strPath

set objRoot = objXml.documentElement

set objNodLst = objRoot.selectNodes("/ROOT/khoved")
for each objNod in objNodLst
  Response.Write("khoved: <br>")
  Response.Write("&nbsp;&nbsp;&nbsp;khovednavn: " & objNod.selectSingleNode("khoved_navn").text & "<br>")
  Response.Write("&nbsp;&nbsp;&nbsp;khovedpris: " & objNod.selectSingleNode("khoved_prisprdeltager").text & "<br>")
next
Avatar billede softspot Forsker
20. august 2005 - 21:35 #5
Ok, det lader til at man skal benytte nodeTypedValue i stedet for nodeValue. Dvs. koden ovenfor kan skrives således:

dim objXml, objRoot
dim strPath

strPath = Server.MapPath("testXml.xml")

set objXml = Server.CreateObject("Microsoft.XMLDOM")
objXml.Load strPath

set objRoot = objXml.documentElement

set objNodLst = objRoot.selectNodes("/ROOT/khoved")
for each objNod in objNodLst
  Response.Write("khoved: <br>")
  Response.Write("&nbsp;&nbsp;&nbsp;khovednavn: " & objNod.selectSingleNode("khoved_navn").nodeTypedValue & "<br>")
  Response.Write("&nbsp;&nbsp;&nbsp;khovedpris: " & objNod.selectSingleNode("khoved_prisprdeltager").nodeTypedValue & "<br>")
next

Bemærk at jeg specifikt benytter selectSingleNode til at hente childnodes, da jeg ikke kan være 100% sikker på at de altid ligger i samme rækkefølge under khoved (det er bare sådan en indgroet livrem-og-seler-politik jeg har antaget med årene :)).

Du skal dog være opmærksom på at koden til fejle noget så grusomt hvis enten khoved_navn eller khoved_prisprdeltager ikke findes under khoved! Det kan der dog checkes for:

if not objNod.selectSingleNode("khoved_prisprdeltager") is nothing then
  Response.Write("&nbsp;&nbsp;&nbsp;khovedpris: " & objNod.selectSingleNode("khoved_prisprdeltager").nodeTypedValue & "<br>")
end if

for nu bare at tage det ene felt som eksempel.
Avatar billede softspot Forsker
20. august 2005 - 21:44 #6
Man kan naturligvis også iterere childnodes og så checke på nodeName for hver enkelt node under en node, men jeg kan bedre lide den direkte tilgang til data, når jeg ved hvad jeg leder efter (jeg har sådan en følelse i maven der siger mig at det performer bedre :))...

Eksempel:
for each objNod in objNodLst
  Response.Write("khoved: <br>")
  for each objChild in objNod.childNodes
    if objChild.nodeName = "khoved_navn" or objChild.nodeName = "khoved_prisprdeltager" then
      Response.Write("&nbsp;&nbsp;&nbsp;" & objChild.nodeName & ": " & objChild.nodeTypedValue & "<br>")
    end if
  next
next

I øvrigt er den heller ikke praktisk hvis man skal hente værdier fra mange felter (selvom jeg kunne finde mere effektive metoder at undersøge om feltnavnet skal bruges, f.eks. instr på en streng der indeholde feltnavnene).
Avatar billede renewester Nybegynder
20. august 2005 - 21:52 #7
Hej softspot

Det var lige præcist dette jeg var ude efter :-D
Jeg har nu de værdier fra XML-filen jeg skal bruge for at arbejde videre med dem i en database.

Kan man evt. også aflæse elementet, så jeg søger gennem alt der ligger under \ROOT\khoved, så jeg kan læse både selve navnet på elementet (f.eks. "khoved_id"), og så den tilhørende værdi (som du allerede har vist mig hvordan jeg læser) ?

Vil du poste som et svar, så jeg kan give dig lidt point?

Tusinde mange tak for hjælpen, Softspot. Det var pænt af dig :-)
Avatar billede softspot Forsker
20. august 2005 - 21:58 #8
Elements navn findes med nodeName (jf. mit sidste eksempel i kommentaren fra 21:44:47).

Det var så lidt. Jeg er glad for at du kunne bruge min erfaring :)
Avatar billede softspot Forsker
21. august 2005 - 10:21 #9
Tak for point :)
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