관리 메뉴

ㄴrㅎnㅂrㄹrㄱi

XML 관련 함수 본문

AUTOHOTKEY/스크립트

XML 관련 함수

님투 2007. 11. 13. 07:31
반응형
XML Reader 2.0
XPath - read and write XML documents with XPath 2.0 syntax
XML Writer




;-------------------------------------------------------------
; XML 파싱
;-------------------------------------------------------------
XMLRead(source, tree, default = "") { ; v2.05 - by Titan
  If source is integer
  {
    DllCall("SetFilePointer", "UInt", source, "UInt", 0, "UInt", 0, "UInt", 0)
    s := VarSetCapacity(c, DllCall("GetFileSize", "UInt", source, "UInt", 0))
    DllCall("ReadFile", "UInt", source, "Str", c, "UInt", s, "UIntP", s, "UInt", 0)
  }
  Else FileRead, c, %source%
  StringGetPos, t, tree, @
  If (ErrorLevel = 0) {
    StringTrimLeft, a, tree, t + 1
    StringLeft, tree, tree, t
  }
  xc = %A_StringCaseSense%
  StringCaseSense, On
  d = >/%A_Tab%`r`n
  Loop, Parse, tree, .
  {
    e = %A_LoopField%
    i = 1
    StringGetPos, t, e, (
    If (ErrorLevel = 0) {
      StringMid, i, e, t + 2, InStr(e, ")") - t - 2
      StringLeft, e, e, t
      i++
    }
    Loop, Parse, d
      StringReplace, c, c, <%e%%A_LoopField%, <%e% %A_LoopField%, A
    ex := "<" . e . " "
    n = %A_Index%
    Loop {
      StringTrimLeft, c, c, InStr(c, ex, 1) - 
      StringReplace, c, c, <, <, UseErrorLevel
      t = %ErrorLevel%
      StringReplace, c, c, />, />, UseErrorLevel
      t -= ErrorLevel
      StringReplace, c, c, </, </, UseErrorLevel
      If (t - ErrorLevel * 2) * -1 - n < 0 or x
        Break
      Else StringTrimLeft, c, c, 1
    }
    StringGetPos, t, c, %ex%, L%i%
    x += ErrorLevel
    StringTrimLeft, c, c, t
    t := InStr(c, "</" . e, 1)
    IfNotEqual, t, 0, StringLeft, c, c, t + StrLen(e) + 2
  }
  If a
    x += !(RegExMatch(c, ex . "[^>]*" . a . "=('|"")(.*?)\1", d) and c := d2)
  Else {
    t := InStr(c, "</" . e . ">", 1)
    x += !t
    StringMid, c, c, InStr(c, ">") + 1, t - 1 - InStr(c, ">")
  }
  StringCaseSense, %xc%
  If x
    c = %default%
  Return, c
}
 
XMLWrite(file, tree, data, type = "", options = "") { ; by Titan - version 1.08
  xSC =%A_StringCaseSense%
  StringCaseSense, On
  xAT =%A_AutoTrim%
  AutoTrim, Off
  FileRead, s, %file%
  StringReplace, tree, tree, (, [, 1
  StringReplace, tree, tree, ), ], 1
  StringReplace, type, type, (, [, 1
  StringReplace, type, type, ), ], 1
  StringReplace, type, type, [", ['
  StringReplace, type, type, "], ']
  If options {
    StringReplace, op, options, %A_Tab%, %A_Space%, 1
    op =%A_Space%%op%%A_Space%
    If InStr(op, " Ind") {
      StringTrimLeft, op_ind, op, InStr(op, " Ind") - 1 + StrLen(" Ind")
      StringLeft, op_ind, op_ind, InStr(op_ind, " ") - 1
      StringReplace, op_ind, op_ind, S, %A_Space%, 1
      StringReplace, op_ind, op_ind, T, %A_Tab%, 1
    }
  }
  If InStr(s, "?>") {
    StringLeft, p, s, InStr(s, "?>") + 1
    StringTrimLeft, s, s, InStr(s, "?>") + 1
  }
  StringReplace, tree, tree, ., ., All UseErrorLevel
  Loop, Parse, tree, .
  {
    e =%A_LoopField%
    op_s := ""
    If InStr(op, " Ind") {
      Loop, % A_Index - 1
        op_s =%op_s%%op_ind%
      StringTrimRight, op_sa, op_s, 1
      op_s =`r`n%op_s%
      op_sa =`r`n%op_sa%
    }
    If InStr(e, "[") and InStr(e, "]") {
      StringMid, i, e, InStr(e, "[") + 1, InStr(e, "]") - InStr(e, "[") - 1
      StringReplace, e, e, [%i%]
      If i is not integer
        error := true
    } Else i =0
    StringReplace, s, s, <%e%>, <%e%%A_Space%>, 1
    IfEqual, ex, %e%, EnvAdd, i, 1
    If !(InStr(s, "<" . e . " ", 1) or InStr(s, "<" . e . ">", 1))
      i =+1
    If (InStr(i, "+") or InStr(i, "-")) and (i != "+0" and i != "-0") {
      If (i < 0) {
        StringLeft, t, s, InStr(s, ">")
        r =%r%%t%
        StringTrimLeft, s, s, InStr(s, ">")
        o =%s%%o%
        s =%op_s%<%e%></%e%>%op_sa%
        Loop, % (i * -1) - 1
          o =%op_s%<%e%></%e%>%o%
      } Else If (i > 0) {
        StringRight, t, s, StrLen(s) - InStr(s, "</", 1, 0) + 1
        o =%t%%o%
        StringTrimRight, s, s, StrLen(s) - InStr(s, "</", 1, 0) + 1
        r =%r%%s%
        s =%op_s%<%e%></%e%>%op_sa%
        Loop, % i - 1
          r =<%e%></%e%>%r%
      }
    } Else {
      i++
      StringGetPos, t, s, <%e%%A_Space%, L%i%
      StringLeft, t1, s, t
      r =%r%%t1%
      StringTrimLeft, s, s, t
      StringLeft, t, s, InStr(s, ">")
      If InStr(t, "/>")
        t := StrLen(s) - InStr(s, "/>") - StrLen("/>")
      Else t := StrLen(s) - InStr(s, "</" . e . ">", 1) + 1 - StrLen("</" . e . ">")
      StringRight, t1, s, t
      o =%t1%%o%
      StringTrimRight, s, s, t
    }
    t := ""
    Loop, % A_Index - 2
      t =%t%%op_ind%
    StringReplace, r, r, `r`n%t%`r`n, `r`n, 1
    StringReplace, r, r, <%e%%A_Space%>, <%e%>, 1
    StringReplace, s, s, <%e%%A_Space%>, <%e%>, 1
    StringReplace, o, o, <%e%%A_Space%>, <%e%>, 1
    ex = %e%
  }
  If !type or type = "string" {
    StringReplace, s, s, %A_Space%/>, />
    StringReplace, s, s, />, ></%e%>
    StringLeft, t, s, InStr(s, ">")
    If (data = "") {
      StringMid, t, s, StrLen("<" . e) + 1, InStr(s, ">") - StrLen("<" . e) - 1
      If t {
        StringMid, t1, s, StrLen("<" . e . t . ">") + 1, InStr(s, "</" . e ">") - StrLen("<" . e . t . ">") - 1
        StringReplace, s, s, <%e%%t%>%t1%</%e%>, <%e%%t% />
        r =%r%%s%
      }
      s := ""
    } Else {
      r =%r%%t%
      StringTrimLeft, s, s, %t%
      StringRight, t, s, StrLen(s) - InStr(s, "</" . e . ">", 1) + 1
      o =%t%%o%
      StringTrimRight, s, s, StrLen(s) - InStr(s, "</" . e . ">", 1) + 1
      s =%data%
    }
  } Else If (InStr(type, "processor") or InStr(type, "attribute")) and (!InStr(type, "['") and !InStr(type, "']"))
    error := true
  If InStr(type, "attribute") {
    StringReplace, type, type, attribute['
    StringReplace, type, type, ']
    StringReplace, s, s, %A_Space%/>, />
    StringReplace, s, s, />, ></%e%>
    StringRight, t, s, StrLen(s) - InStr(s, ">")
    o =%t%%o%    
    StringTrimRight, s, s, StrLen(s) - InStr(s, ">")
    If InStr(s, type . "=") {
      StringRight, t, s, StrLen(s) - (InStr(s, type) + StrLen(type . "="))
      StringLeft, t, t, InStr(t, """") - 1
      If (data = "")
        StringReplace, s, s, %A_Space%%type%="%t%"
      Else StringReplace, s, s, %A_Space%%type%="%t%", %A_Space%%type%="%data%"
    } Else If data
      StringReplace, s, s, <%e%, <%e%%A_Space%%type%="%data%"
    StringReplace, s, s, <%e%%A_Space%%A_Space%, <%e%%A_Space%
    StringLeft, t1, o, StrLen("</" . e . ">")
    If (t1 == "</" . e . ">") {
      StringTrimLeft, o, o, StrLen("</" . e . ">")
      StringReplace, s, s, >, %A_Space%/>
    }
  } Else If InStr(type, "processor") {
    StringReplace, type, type, processor['
    StringReplace, type, type, ']
    If !p
      p =<?xml %type%="%data%"?>
    Else If InStr(p, type . "=") {
      StringRight, t, p, StrLen(p) - InStr(p, type) - StrLen(type . "=")
      StringLeft, t, t, InStr(t, """") - 1
      StringReplace, p, p, type . "=""" . t . """", % type . "=""" . data . """"
    } Else StringReplace, p, p, ?>, %A_Space%%type%="%data%"?>
  }
  StringLeft, t, r, 2
  IfEqual, t, `r`n, StringTrimLeft, r, r, 2
  AutoTrim, %xAT%
  StringCaseSense, %xSC%
  If error
    Return, true
  FileDelete, %file%
  FileAppend, %p%%r%%s%%o%, %file%
  Return, ErrorLevel
}
 
; 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 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 or il = -1
        exp = <(%test%)\b(?:[^>]*/|.+?</\1)>
      Else if ils
        exp = (%lf%%ic%*)<(%test%)\b(?:[^>]*/|.+?\1%ic%</\2)>
      Else exp = (%lf%%ic%{%il%})<(%test%)\b(?:[^>]*/|.+?\1%ic%</\2)>
      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%</%test%>
          a1 := InStr(doc, lf . all . "</", "", a1) - 1
            , doc := SubStr(doc, 1, a1) . a . SubStr(doc, a1 + 1)
            , xml := a1 + StrLen(test) + 4 + StrLen(all) . "-0"
          Break
        }
        Else If A_LoopField = -1
        {
          StringSplit, a, col1, -
          all =
          Loop, % il - 1
            all .= ic
          a = %all%<%test%>%lf%%all%%ic%</%test%>%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<Name>@?\w+(?:\(\))?)(?:(?P<Eq>[<>=!]+)[""']?(?P<Match>.+)[""']?)?", test)
        If testName = last()
          new := col%col0%
        Else {
          exp := InStr(testName, "@") ? "\b(?<=" . SubStr(testName, 2)
            . "=(['""]))[^\1]*?(?=\1)" : "(?<=<" . testName . ">).*?(?=(?:"
            . lf . ic "+)?</" . 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%
      }
      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, "<?xml")
    doc = %lf%<?xml version="1.0" encoding="iso-8859-1"?>%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
}
 
반응형

'AUTOHOTKEY > 스크립트' 카테고리의 다른 글

글자를 포함한 스크린 샷을 찍습니다.  (0) 2007.12.22
AHK Chat (Another Method)  (0) 2007.11.25
ado com  (0) 2007.11.10
AHK BBCodeWriter v7.0.2 - An offline BBCode Editor  (0) 2007.11.04
AHK Automated Installation  (0) 2007.11.04
Comments