; by Titan, v1.03; http://www.autohotkey.net/~Titan/dl/xpath.html XPath(ByRef doc, step, set = "") { StringReplace, step, step, *, \w+, All lf = `n ic =   isTxt := InStr(step, "/text()") Loop, Parse, step, |, `r  `n { xml := "1-" . StrLen(doc) il = 0 Loop, Parse, A_LoopField, /, `r  `n { If A_LoopField = { If A_Index > 1 { il = -1 ils = 1 } Continue } If pos := InStr(A_LoopField, "[") test := SubStr(A_LoopField, 1, pos - 1), pred := SubStr(A_LoopField, pos) Else { test = %A_LoopField% pred = } If test = text() { If atr exp = (?<=([""']))[^\1]*(?=\1) Else exp = (?<=%testLast%).*(?=]*/|.+? Else if ils exp = (%lf%%ic%*)<(%test%)\b(?:[^>]*/|.+?\1%ic% Else exp = (%lf%%ic%{%il%})<(%test%)\b(?:[^>]*/|.+?\1%ic% all = Loop, Parse, xml, `, { StringSplit, a, A_LoopField, - StringMid, a, doc, a1, a2 pos = 0 Loop If pos := RegExMatch(a, "Ss)" . exp, match, 1 + pos) all .= pos + a1 - 1 . "-" . StrLen(match) . "," Else Break } If all StringTrimRight, xml, all, 1 Else If atr doc := SubStr(doc, 1, a1 := InStr(doc, ">", "", a1) - 1) . " " . SubStr(test, 2) . "=""""" . SubStr(doc, a1 + 1) , xml := a1 + StrLen(test) + 3 . "-0" il++ Loop, Parse, pred, [] { If A_LoopField = Continue StringSplit, col, xml, `, If A_LoopField is digit { xml := col%A_LoopField% Break } Else If A_LoopField = +1 { StringSplit, a, col%col0%, - all = Loop, % il - 1 all .= ic a = %lf%%all%<%test%>%lf%%all%%ic% a1 := InStr(doc, lf . all . "%lf%%all%%ic%%lf%%all% doc := SubStr(doc, 1, a1) . a . SubStr(doc, a1) , xml := a1 + StrLen(test) + 3 + StrLen(all) . "-0" Break } RegExMatch(A_LoopField , "S)(?P@?\w+(?:\(\))?)(?:(?P[<>=!]+)[""']?(?P.+)[""']?)?", test) If testName = last() new := col%col0% Else { exp := InStr(testName, "@") ? "\b(?<=" . SubStr(testName, 2) . "=(['""]))[^\1]*?(?=\1)" : "(?<=<" . testName . ">).*?(?=(?:" . lf . ic "+)?)" new = Loop, Parse, xml, `, { If testName = position() test = %A_Index% Else { StringSplit, a, col%A_Index%, - StringMid, a, doc, a1, a2 RegExMatch(a, "Ss)" . exp, test) } new .= (testMatch ? (testEq = "=" ? test == testMatch : testEq = "!=" ? test != testMatch : testEq = "<" ? test < testMatch : testEq = "<=" ? test <= testMatch : testEq = ">" ? test > testMatch : testEq = ">=" ? test >= testMatch : 0) ? 1 : 0 : 1) ? col%A_Index% : "" } } xml = %new% } If isTxt { StringSplit, a, xml, - StringMid, a, doc, a1, a2 RegExMatch(a, "<" . test . "[^>]*>", testLast) } } sel .= xml } all = test = 0 Loop, Parse, sel, `, { StringSplit, a, A_LoopField, - If a1 = 1 Continue all .= (prev := SubStr(doc, a1 += test, a2)) . "," If set doc := SubStr(doc, 1, a1 - 1) . set . SubStr(doc, a1 + a2) , test := StrLen(set) - StrLen(prev) } If !InStr(doc, "%lf%%doc% Return, SubStr(RegExReplace(all, lf . ic . "+(?=<|,|$)"), 1, -1) } XmlDoc(src, set = "") { lf = `n VarSetCapacity(ic, 255, 160) If set { StringTrimLeft, set, set, InStr(set, "<") - 1 FileDelete, %src% FileAppend, % RegExReplace(set, lf . SubStr(ic, 1, 1) . "+(?=<|,|$)"), %src% Return, ErrorLevel } If InStr(src, "http://") = 1 { uri = %src% SplitPath, uri, name src = %A_Temp%\%name% UrlDownloadToFile, %uri%, %src% } If FileExist(src) FileRead, src, %src% If !InStr(src, "<") Return il = 0 pos = 1 Loop If RegExMatch(src, "(?<=]*))>", tag, pos) { StringReplace, str, tag, <, <, All StringReplace, src, src, %tag%, %str%, All pos += StrLen(tag) } Else Break StringReplace, src, src, `,, ,, All StringTrimLeft, src, src, InStr(src, "<") VarSetCapacity(doc, StrLen(src)) Loop, Parse, src, < { doc .= lf . SubStr(ic, 1, il) . "<" . A_LoopField If InStr(A_LoopField, "/") = 1 il-- Else If !RegExMatch(A_LoopField, "^[^>]*/>") and InStr(A_LoopField, "?") != 1 and InStr(A_LoopField, "!") != 1 il++ } Return, doc }