; by Titan, v1.01; http://www.autohotkey.net/~Titan/dl/xpath.html XPath(ByRef doc, step, set = "") { StringReplace, step, step, *, \w+, All lf = `n ic =   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 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 = (?<=>)[^<]*(?=<) } Else If test = remove() { all = %doc% doc = Loop, Parse, xml, `, { StringSplit, a, A_LoopField, - doc .= SubStr(all, 1, a1) . SubStr(all, a1 + a2) } xml = Break } Else If atr := InStr(test, "@") = 1 exp := "\b" . SubStr(test, 2) . "=(['""]).*?\1" Else If il = -1 exp = <(%test%)\b(?:[^>]*/|.+? Else exp = %lf%%ic%{%il%}<(%test%)\b(?:[^>]*/|.+?%lf%%ic%{%il%}%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 -= il) . " " . 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 . ">).*?(?=)" 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% } } sel .= xml } all = test = 0 Loop, Parse, sel, `, { StringSplit, a, A_LoopField, - 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 }