Text im Text suchen

Startseite Foren Deutsches LiveCode-Forum Text im Text suchen

Schlagwörter: 

Ansicht von 13 Antwort-Themen
  • Autor
    Beiträge
    • #21840
      Gil
      Teilnehmer

      hi,

      wie kann ich in LC in einem Text nach einer bestimmten Zeichenkette suchen?

      Am Besten per Beispiel:

      Es wird ein Smarthome-System abgefragt. Diese gibt einen (XML)-Text zurück:

      device name=“Fenster Büro“ device_id=“4711″
      state ise_id=“2881″ value „1“
      bla bla…
      device
      device name „Fenster Wohnzimmer“ device_id=“4712″
      blabla

      state ise_id=“2695″ value „2“
      bla bla

      device

      Nun möchte ich nach „state ise_id=“2695“ suchen.
      Die folgenden Werte in der Zeile wie value benötige ich auch.

      Wie bekomme ich das am Besten hin?
      Frage ich die Werte alle einzeln ab, kollabiert die Smarthome-Zentrale wegen zu vieler Anfragen.
      hmm.

      Danke vorab und liebe Grüße
      Gil

    • #21844
      Torsten
      Teilnehmer

      Hi Gil,

      verstehe ich richtig, dass Du eine XML-Datei hast und darin suchst?
      Wobei Dein Beispieltext ja kein XML ist?

      Wie dem auch sei, wenn Deine Info in derselben Zeile wie der Suchbegriff ist, dann kannst Du es einfach so machen:

      put line lineoffset("state ise_id=" & quote & "2695" & quote, tDieXMLDatei) of tDieXMLDatei into tDieGesuchteZeile

      Jetzt hast Du in tDieGesuchteZeile die Zeile state ise_id="2695" value "2" drin.
      Wenn Du jetzt an den Wert von value ran willst, kannst Du es Dir einfach machen, falls das Schema immer gleich bleibt:

      set itemdelimiter to quote
      put item 4 of tDieGesuchteZeile into tValue

      Das funktioniert aber nur, wenn der Wert von value immer genau an dieser Stelle steht und keine anderen Parameter dazwischen stehen. Falls das der Fall sein sollte, kannst Du folgendes machen:

      set itemdelimiter to "value " & quote -- das Leerzeichen ist wichtig, da der String ja value "2" heisst
      put trueword 1 of item 2 of tDieGesuchteZeile into tValue

      Teste das mal aus, bei mir geht es so.

      Happy Coding
      Torsten

    • #21850
      Gil
      Teilnehmer

      hi Torsten,

      vielen Dank für die schnelle Antwort.
      Ich habe das Script ausprobiert – ét voila: es funktioniert, danke!

      Leider tut sich ein anderes Problem auf:

      Wenn das XML ausgelesen wird, besteht es aus einer einzigen Zeile.
      Also nicht so schön (Zeile für Zeile) wie z.B. im Browser oder mit Notepad++

      Anbei mein Script, wie ich die Daten aus der CCU (Smarthome-Zentrale) hole:

      on mouseDown pButtonNumber
         --tsNet initialisieren
         tsNetInit
         
         -- Zertifikat deaktiveren:
         tsNetVerifySSLPeer false
         
         put true into tSettings["force_digest_auth"]
         put "" into tSettings["username"]
         put "" into tSettings["password"]
         
         put tsNetGetSync("http://192.168.178.57/config/xmlapi/statelist.cgi", tHeaders, tRecvHeaders, tResult, tBytes) into tData
         
         put tData into fld "Info"
         
      end mouseDown
      

      Vielleicht hast Du noch einen Rat.

      Viele GRüße
      Gil

    • #21853
      Klaus Major
      Verwalter

      Poste doch mal den langen String hier!

    • #21857
      Gil
      Teilnehmer

      hi Klaus,

      wie Du meinst:


      <?xml version=“1.0″ encoding=“ISO-8859-1″ ?><state><datapoint ise_id=’4715′ value=’0’/><datapoint ise_id=’2995′ value=’0’/><datapoint ise_id=’4459′ value=’0’/></state>

      viel Spaß 🙂

    • #21858
      Gil
      Teilnehmer

      würde es den gehen, wenn man hinter jedem „>“ ein „Return“ einbauen kann?
      Damit wäre es dann wieder Zeile für Zeile…

    • #21859
      Klaus Major
      Verwalter

      Danke, aber es heisst DENN, würde es DENN gehen. Wie man’s spricht!

      Ja, das sollte klappen:

      ...
      replace ">" with (">" & CR) in tXMLString
      ...

      Dann kannst Du wieder mit Torstens Skript nach der gesuchten Zeile gucken.

    • #21861
      Gil
      Teilnehmer

      hi Klaus,
      immer diese Rechtschreibfehler…

      Klasse! Hat funktioniert!!!

      Ganz liebe Grüße und tausend Dank!

      Gil

    • #21864
      Axwald
      Teilnehmer

      Hallo,

      für solche Fälle (Suche nach Werten innerhalb von bestimmten Tags) habe ich mir mal eine Funktion geschrieben – es kommt ja häufiger vor, daß die Daten in einem Wust an redundanten Tags versteckt sind.

      Mit dem Beispiel von oben sieht das dann so aus:

      on mouseUp
         put "<?xml version='1.0' encoding='ISO-8859-1' ?>" & \
               "<state><datapoint ise_id='4715' value='0'/>" & \
               "<datapoint ise_id='2995' value='0'/>" & \
               "<datapoint ise_id='4459' value='0'/>" & \
               "</state>" into myData                             --  Daten laden
         put "2995" into myStrg                                   --  Gesucht
         put 0 into myCnt                                         --  Zähler
         
         repeat until (the controlKey is down)                    --  Schleife mit Sicherheit ...
            put inBeet(myData,"datapoint ise_id='","'/>",myCnt) into myVar
            if myVar is empty then                                --  Nix mehr da, fertig!
               exit repeat
            else
               put line 1 of myVar into myCnt                      --  von hier aus weitersuchen ...
               if line 2 of myVar begins with myStrg then          --  ist es das Richtige?
                  put line 2 of myVar & CR after myRes              --  dann merken
               end if
            end if 
         end repeat
         answer information char 1 to -2 of myRes titled "Ergebnis:"  --  Antworten
      end mouseUp
      
      function inBeet theString, theStart, theEnd, offNum
         /* inBeet() is a very fast function to find things - 
         It extracts data from "theString" that are between "theStart" and "theEnd",
         and returns the first hit. If it doesn't find a match,
         it returns empty.   
         2 modes of action, depending on the value of "offNum" (see below).
         
         # theString (String): The data you're searching in. This can be huge :)
         
         # theStart, theEnd (String): what is before and after your desired text
         .  (it is assumed that theEnd comes AFTER theStart, and that both are not empty ...)
         
         # OffNum (Int, optional) allows you to skip [offNum] chars at the beginning of theString
         . When empty, it just returns the first found string, or empty;
         . Else (offNum => 0) it returns a 2-line result:
         .   line 1 is the position of the last char touched in theString (= last char found of theEnd).
         .   And line 2 is the found string.
         
         What negative values do for offNum is left as an exercise - it has a (strange) use too!  
         GPL V3, axwald @ forums.livecode.com 2020   */
         
         if offNum is not empty then
            put offset(theStart,theString,offNum) + len(theStart) + offNum into myStart
            if myStart is (len(theStart) + offNum) then return empty
            put offset(theEnd,theString,myStart) + (myStart)-1 into myEnd
            if myEnd is (myStart)-1 then return empty
            return myEnd & CR & char myStart to myEnd of theString
         else
            return char (offset(theStart,theString) + len(theStart)) to \
                  (offset(theEnd,theString,(offset(theStart,theString) + len(theStart))) \
                  + (offset(theStart,theString) + len(theStart))-1) \
                  of theString
         end if
      end inBeet

      Das findet alle Vorkommen von „datapoint ise_id=’2995“ und listet sie auf:

      2995' value='0
      2995' value='1

      (Wenn es den 2ten gäbe – mit o.a. Daten kommt nur die erste Zeile.)

      Wenn Du weißt, daß es nur ein „2995“ gibt, dann geht es auch so:
      answer information inBeet(myData,"datapoint ise_id='2995' value='","'/>") titled "Ergebnis:"
      Das findet den ersten Wert zu „2995“: „0“

      Viel Spaß!

    • #21868
      Gil
      Teilnehmer

      hi Axwald,

      coooooool – diesmal bewusst mit Rechtschreibfehler 🙂

      Danke und viele Grüße
      Gil

      PS: ja die Antwort der Homematic CCU ist recht üppig, wenn man nicht gezielt abfragt.
      Da ist Dein Tool echt klasse.

    • #21869
      Gil
      Teilnehmer

      hi Axwald,

      irgendwie will es bei mir nicht mit einer komplexeren XML.
      Hier ein Auszug:


      <device name=“Büro Fenster“ ise_id=“2950″ unreach=“false“ sticky_unreach=“false“ config_pending=“false“>
      <channel name=“Büro Fenster:0″ ise_id=“2951″ visible=““ operate=““>
      <datapoint name=“BidCos-RF.IEQ0205608:0.UNREACH“ type=“UNREACH“ ise_id=“2967″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.IEQ0205608:0.STICKY_UNREACH“ type=“STICKY_UNREACH“ ise_id=“2963″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“7″/>
      <datapoint name=“BidCos-RF.IEQ0205608:0.CONFIG_PENDING“ type=“CONFIG_PENDING“ ise_id=“2953″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.IEQ0205608:0.LOWBAT“ type=“LOWBAT“ ise_id=“2957″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595340388″ operations=“5″/>
      <datapoint name=“BidCos-RF.IEQ0205608:0.RSSI_DEVICE“ type=“RSSI_DEVICE“ ise_id=“2961″ value=“1″ valuetype=“8″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.IEQ0205608:0.RSSI_PEER“ type=“RSSI_PEER“ ise_id=“2962″ value=“209″ valuetype=“8″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      </channel>
      <channel name=“Büro Fenster“ ise_id=“2971″ visible=“true“ operate=“true“>
      <datapoint name=“BidCos-RF.IEQ0205608:1.STATE“ type=“STATE“ ise_id=“2995″ value=“0″ valuetype=“16″ valueunit=““ timestamp=“1595426260″ operations=“5″/>
      <datapoint name=“BidCos-RF.IEQ0205608:1.ERROR“ type=“ERROR“ ise_id=“2972″ value=“0″ valuetype=“16″ valueunit=““ timestamp=“1595426260″ operations=“5″/>
      <datapoint name=“BidCos-RF.IEQ0205608:1.LOWBAT“ type=“LOWBAT“ ise_id=“3644″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595426260″ operations=“5″/>
      </channel>
      </device>
      <device name=“Büro Heizung“ ise_id=“1607″ unreach=“false“ sticky_unreach=“false“ config_pending=“false“>
      <channel name=“Büro Heizung:0″ ise_id=“1608″ visible=““ operate=““>
      <datapoint name=“BidCos-RF.JEQ0233943:0.UNREACH“ type=“UNREACH“ ise_id=“1623″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.JEQ0233943:0.STICKY_UNREACH“ type=“STICKY_UNREACH“ ise_id=“1619″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“7″/>
      <datapoint name=“BidCos-RF.JEQ0233943:0.CONFIG_PENDING“ type=“CONFIG_PENDING“ ise_id=“1609″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.JEQ0233943:0.LOWBAT“ type=“LOWBAT“ ise_id=“1613″ value=“false“ valuetype=“2″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.JEQ0233943:0.RSSI_DEVICE“ type=“RSSI_DEVICE“ ise_id=“1617″ value=“1″ valuetype=“8″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      <datapoint name=“BidCos-RF.JEQ0233943:0.RSSI_PEER“ type=“RSSI_PEER“ ise_id=“1618″ value=“195″ valuetype=“8″ valueunit=““ timestamp=“1595149763″ operations=“5″/>
      </channel>
      <channel name=“Büro Heizung“ ise_id=“1627″ visible=“true“ operate=“true“>
      <datapoint name=“BidCos-RF.JEQ0233943:1.VALVE_STATE“ type=“VALVE_STATE“ ise_id=“1641″ value=“0″ valuetype=“16″ valueunit=“%“ timestamp=“1595431247″ operations=“5″/>
      <datapoint name=“BidCos-RF.JEQ0233943:1.ERROR“ type=“ERROR“ ise_id=“1628″ value=“0″ valuetype=“16″ valueunit=““ timestamp=“1595431247″ operations=“5″/>
      </channel>
      </device>

      Hier möchte ich zum den Datenpunkt (datapoint_id) 2995 abfragen.

      Vermutlich ist es das „End-Tag“ – oder?

      LG
      Gil

    • #21872
      Klaus Major
      Verwalter

      Hi Gil,

      bei solchen komplexen XML-Dateien lohnt es sich sicher, mal einen Blick auf das XML External von LC zu werfen. Nicht so einfach in der Bedienung, aber sehr mächtig!

      Hier gibt es eine Lektion dazu von LC:
      http://lessons.livecode.com/m/4071/l/7011-how-to-read-in-data-from-an-xml-file

      Gruß

      Klaus

    • #21878
      Axwald
      Teilnehmer

      Hallo,

      wenn ich das recht interpretiere, geht es darum, ob das Büro-Fenster offen oder zu ist? (Typ ‚State‘, Value „0“ – geschlossen?)

      Wir brauchen eindeutige Werte für „davor“ und „danach“, also:

         put "C:/Users/myName/Desktop/state.txt" into myFile  --  dein Beispiel
         put URL ("file:" & myFile) into myData
         --  ise_id="2995" value="  | ist davor, also:
         put "ise_id=" & quote & "2995" & quote & " value=" & quote into myStart
         --  " valuetype            | kommt danach, also:
         put quote & " valuetype" into myEnd
         
         answer information "Value = " & inBeet(myData, myStart, myEnd) titled "Ergebnis:"
      

      Etwas frickelig, die Verkettung der Variablen mit den Quotes …

      Viel Spaß!

    • #21882
      Gil
      Teilnehmer

      hi @all,

      es läuft jetzt!
      Sowohl mit der Abfrage von Thorsten und der von Axwald!

      Besten Dank, Ihr Lieben!

Ansicht von 13 Antwort-Themen
  • Du musst angemeldet sein, um auf dieses Thema antworten zu können.