Привет. Есть XML код, никак не могу найти общий алгоритм как распарсить его. Код (Text): <time day="2014-10-10"> <symbol number="600" name="light snow" var="13d"/> <precipitation value="0.5" type="snow"/> <windDirection deg="253" code="WSW" name="West-southwest"/> <windSpeed mps="6.26" name="Moderate breeze"/> <temperature day="-1.13" min="-4.58" max="-1.13" night="-4.58" eve="-2.28" morn="-2.29"/> <pressure unit="hPa" value="1013.81"/> <humidity value="61" unit="%"/> <clouds value="overcast clouds" all="88" unit="%"/> </time> Нужно выделить: Day="2014-10-10" var="13d" value="0.5"; type="snow" code="WSW" mps="6.26" day="-1.13"; night="-4.58" value="1013.81" value="61" all="88"
Сходу приходит в голову решение задачи "в лоб". Можно смастерить функцию, которая будет принимать имя узла и имя атрибута, а возвращать значение атрибута. Если структура документа не меняется, то должно прокатить. void GetValue(char* text, char* nodeName, char* attrName, char* result); Алгоритм может быть таким: найти в тексте первое вхождение имени узла; начиная поиск с найденной позиции найти первое вхождение имени атрибута (можно еще контролировать, что до нахождения имени атрибута не должен встретиться символ '>'); начиная поиск с позиции атрибута найти первую и вторую кавычку и вытащить то, что находится между ними; в случае неудачного поиска на любом шаге вернуть NULL. Функцию нужно будет вызвать для каждого атрибута с соответствующими параметрами. char Day[11]; GetValue(text, "time", "day", Day); Такого алгоритма будет достаточно?
Общая идея мне понятна, однако приведенный выше XML на момент обработки имеется не в полном виде, а вычитывается из клиента побайтно. Код (Text): while (!client.available()); while (client.available()) {ReadByte();} } ..... void ReadByte() { char inChar = client.read(); // Обработка // } Структура документа постоянна.
Можно же сначала целиком прочитать документ и затем подать его на вход парсера. Либо принимать отдельно каждый узел, это сэкономит память.
Принять документ - памяти не хватит, на узел - тоже, а вот строку наверное можно попробовать. На Си, к сожалению пока что нет.
Эх, жаль. Но это не так сложно, как кажется. Вы просто объявляете количество состояний, равное количеству синтаксических элементов, потом внутри каждого состояния проверяете каждый новый символ на соответствие алфавиту этого элемента или шаблону, при этом накапливаете символы в строке (буфере), как только встречаете несоответствие - переходите к следующему элементу. Так исходный поток разбивается на токены, а уж из них вытащить данные - плевое дело. Собственно, разбор частично повторяется еще раз, но вместо отдельных символов вы уже работаете с элементами XML.
Ну т.е. сначала ищите во входном потоке начало тэга "<". Если нашли - переходите к считыванию имени тэга, как только встретился пробел - все, начинаете распознавать аргументы, точно так же, ключ, "=", значение. Если встречаете ">" или "/>" переходите на чтение ветви DOM или к следующему узлу этого же уровня и т.д. Т.к. весь текст в памяти не хранится - данные извлекаете сразу как будет обнаружена тройка токенов "ключ", "=", "значение", идущих подряд.
В библиотеке <stdlib.h> есть функция double atof(const char* nptr). Может подойдет? Потому как strtof сидит в той же библиотеке, но вот в AVR ее нет.
Похоже, что ТО что нужно. Вечером попробую. Спасибо. В общем написал я парсер. Изначально воспользовался алгоритмом разборщика XML из интернета http://forum.arduino.cc/index.php/topic,39023.0.html , с его помощью я накапливаю содержимое 1 строки в массив, после чего разбираю строку с помощью объекта String.
Ну вот, все работает как надо. Всем спасибо за советы и идеи! Осталось только строки: sun rise: 2014-10-14T00:18:33 sun set: 2014-10-14T10:51:01 перевести в дату и время. Информацию о восходе хочу использовать для корректировки показаний уличного датчика температуры, т.к. он на солнечной стороне висит.