views:

355

answers:

2

I have an XML like this

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">1</int>
    <lst name="params">
        <str name="start">num</str>
        <str name="fl">string</str>
        <str name="q">string</str>
        <str name="rows">num</str>
        <str name="op">string</str>
        <str name="sort">string</str>
    </lst>
</lst>
<result name="response" numFound="20" start="1">
    <doc>
        <arr name="URL"><str>string</str></arr>
        <arr name="ID"><int>1</int></arr>
    </doc>
    <doc>
        <arr name="URL"><str>string</str></arr>
        <arr name="ID"><int>2</int></arr>
    </doc>  
    <doc>
        <arr name="URL"><str>string</str></arr>
        <arr name="ID"><int>3</int></arr>
    </doc>      
    <doc>
        <arr name="URL"><str>string</str></arr>
        <arr name="ID"><int>4</int></arr>
    </doc>      
</result>
</response>

I need to find the ordinal position of element doc which child node arr/id has text value 2

I am Using Classic ASP

thanks

+1  A: 

You can't directly, you must count nodes. I would do

xpath = "/response/result/doc[number(arr[@name='ID']) = 2]"
Set DocNode = XmlDoc.SelectSingleNode(xpath)

If DocNode Is Nothing
  position = 0  ''# not found
Else
  position = DocNode.SelectNodes("./preceding-sibling::doc").length + 1
End If
Tomalak
@tomalak: It keep Saying Object required: 'DocNode' i think probably the xpath query wrong since 2 is the value of int element inside arr element, but i have not enough xpath experience
Ariel
@chazzuka: For your sample XML, my XPath selects the second <doc> node, I've just double-checked. Can it be that your XML looks a bit differently in reality?
Tomalak
@tomalak: the xml is exactly the same, now it give me 0 everytime. does it because the 2 value is inside int element? response/doc/arr/int
Ariel
@chazzuka: No, that's not the reason. Please post your complete XML, I'm sure the error is somewhere else. Probably `<response>` is not the first element in your XML.
Tomalak
@tomalak: thank you for your help, i have updated the source
Ariel
@chazzuka: Try again, please. Also, do some reading on XPath. ;-)
Tomalak
+1  A: 

Use e.g.

Set doc = Server.CreateObject("Msxml2.DOMDocument.3.0")
doc.async = False
If doc.load(Server.MapPath("input.xml")) Then
  doc.setProperty "SelectionLanguage", "XPath"
  Set docEl = doc.selectSingleNode("response/result/doc[arr[@name = 'ID'] = 2]")
  If Not(doc Is Nothing) Then
    Response.Write(docEl.selectNodes("preceding-sibling::doc").length)
  Else
    Response.Write("Not found.")
  End If
Else
  Response.Write doc.parseError.reason
End If

As already pointed out, if you want the index to start with 1 and not 0 then you need to add 1 to the result.

Martin Honnen
@Martin: In what way does that answer differ from mine? (I mean, conceptional differences, not that I took `SelectionLanguage` for granted and used `Count` instead of the correct `length`)
Tomalak
Wow awsome, thank you @Martin + @Tomalak
Ariel
Tomalak, when I wrote my answer the XPath in your answer did not match the latest sample of the poster and he did say it did not work for him. So I wrote an answer trying to correct the XPath and correcting other flaws (like Count instead of length and not setting the SelectionLanguage) that people often trip over when using MSXML.
Martin Honnen
@Martin: As you might have derived from the comments below my answer: The question did not reflect the actual problem, and the OP changed his input XML on my request. I know there is nothing formally "wrong" with what's basically "copying an answer", it's just not… nice. Sorry, but that I got `Count` wrong is no argument, and when the OP changes the question in mid-air then there is a certain chance that my answer does not reflect that for a short period of time, so that doesn't really count either.
Tomalak
Tomalak, I have no idea what you complain about, I simply tried to help the original poster with some working code which had not been posted when I looked at the question and the answers and comments. If you think that I copied your answer then that's your problem, rest assured that I fired up my text editor and typed that code without copying any of yours.
Martin Honnen