Почему функция XMLDocument :: FirstChild () в TinyXML2 возвращает NULL при попытке проанализировать этот действительный файл XML? - PullRequest
0 голосов
/ 27 сентября 2018

Я знаю, что, возможно, здесь есть кое-что очевидное, чего мне не хватает, но это уже несколько дней сводит меня с ума.

Вот простая функция, которую я написал, которая должнанайдите первый тег в документе XML на данный момент:

void parse_weather_file(const char* weatherFileName, WeatherDataAsPWMValues *wd)
{
    if (wd == NULL) return;

    std::cout << weatherFileName << std::endl;

    tinyxml2::XMLDocument doc(weatherFileName);
    tinyxml2::XMLNode *root = doc.FirstChild();
    if (root == NULL) std::cout << "Error" << std::endl;
}

Вот XML-документ, который я пытаюсь проанализировать:

<!-- Sample output of openWeatherMap API -->
<?xml version="1.0" encoding="utf-8"?>
<current>
    <city id="2643741" name="City of London">
        <coord lon="-0.09" lat="51.51">
        <country>GB</country>
    <sun rise="2015-06-30T03:46:57" set="2015-06-30T20:21:12">
    </city>
    <temperature value="72.34" min="66.2" max="79.88" unit="fahrenheit"/>
    <humidity value="43" unit="%">
    <pressure value="1020" unit="hPa">
    <wind>
        <speed value="7.78" name="Moderate breeze">
        <direction value="140" code="SE" name="SouthEast">
    </wind>
    <clouds value="0" name="clear sky">
    <visibility value="10000">
    <precipitation mode="no">
    <weather number="800" value="Sky is Clear" icon="01d">
    <lastupdate value="2015-06-30T08:36:14">
</current>

А вот вывод, который я получаю изfunction:

test.xml
Error

Это предполагает, что root равно NULL в конце функции, но я не уверен, почему это так.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Как объяснил @ zx485, ваш XML искажен.Но даже после исправления ваш код все равно не будет работать.Согласно документации TinyXML-2 , класс tinyxml2::XMLDocument НЕ имеет конструктора, который принимает имя файла в качестве входных данных.Однако он имеет конструктор, который принимает bool в качестве ввода:

XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );

A const char* неявно преобразуется в bool, поэтому ваш код компилируется, но вы нефактически загружает файл вообще, поэтому root имеет значение NULL.

Вместо этого вам необходимо вызвать метод класса LoadFile():

XMLError LoadFile( const char* filename );

Например:

void parse_weather_file(const char* weatherFileName, WeatherDataAsPWMValues *wd)
{
    if (wd == NULL) return;

    std::cout << weatherFileName << std::endl;

    tinyxml2::XMLDocument doc;

    XMLError err = doc.LoadFile(weatherFileName);
    if (err != XML_SUCCESS) {
        std::cout << "Error loading file: " << (int)err << std::endl;

        /* or:

        std::cout << "Error loading file: " << doc.ErrorName() << std::endl;

        std::cout << "Error loading file: " << tinyxml2::XMLDocument::ErrorIDToName(err) << std::endl;

        std::cout << "Error loading file: " << doc.ErrorStr() << std::endl;

        std::cout << "Error loading file" <<< endl;
        doc.PrintError();

        */

        return;
    }

    tinyxml2::XMLNode *root = doc.FirstChild();
    if (root == NULL) {
        std::cout << "Error root is null" << std::endl;
        return;
    }

    // use root as needed...
}

Кроме того, вы должны использовать метод RootElement() вместо метода FirstChild():

tinyxml2::XMLElement *root = doc.RootElement();
0 голосов
/ 27 сентября 2018

Я сделал ваш XML правильно сформированным , добавив закрывающий / для отдельных элементов.
Вот как это выглядит:

<?xml version="1.0" encoding="utf-8"?>
<current>
    <city id="2643741" name="City of London">
        <coord lon="-0.09" lat="51.51" />
        <country>GB</country>
        <sun rise="2015-06-30T03:46:57" set="2015-06-30T20:21:12" />
    </city>
    <temperature value="72.34" min="66.2" max="79.88" unit="fahrenheit" />
    <humidity value="43" unit="%" />
    <pressure value="1020" unit="hPa" />
    <wind>
        <speed value="7.78" name="Moderate breeze" />
        <direction value="140" code="SE" name="SouthEast" />
    </wind>
    <clouds value="0" name="clear sky" />
    <visibility value="10000" />
    <precipitation mode="no" />
    <weather number="800" value="Sky is Clear" icon="01d" />
    <lastupdate value="2015-06-30T08:36:14" />
</current>

Надеюсь, это поможет вам выявить ошибки...

...