Retrieve single value from XML file

Hello!

I want some "simple" way to extract a value out of a XML file stored online.

link:
https://opendata-download-metobs.smhi.se/api/version/latest/parameter/21/station/77210/period/latest-hour/data.xml

it is the "value" that i want.

Any ideas or examples in the most simplest way to do this?
Ive seen something called rapidXML however, it seem rather complex for this task.
Or, maybe, that is the only way?
Put the whole lot into a string.

http://www.cplusplus.com/reference/string/string/find_last_of/ to find the last <value>

http://www.cplusplus.com/reference/string/string/find/ to find </value>

With that information, copy the characters between them into a new string.

http://www.cplusplus.com/reference/string/stof/ to turn that new string into a float
Using the standard regular expressions library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <string>
#include <regex>
#include <cmath>
#include <sstream>

double extract_value( std::istream& stm )
{
    // see: http://xenon.stanford.edu/~xusch/regexp/analyzer.html?regex=%5Cs*%3Cvalue%3E%5Cs*%28%5Cd+%5C.%3F%5Cd*%29%5Cs*%3C/value%3E%5Cs*&env=env_java
    static const std::regex re( "\\s*<value>\\s*(\\d+\\.?\\d*)\\s*</value>\\s*" ) ;

    std::string line ;
    while( std::getline( stm, line ) )
    {
        std::smatch match ;
        if( std::regex_match( line, match, re ) ) return std::stod( match[1] ) ;
    }

    return std::nan("") ; // return NaN on failure
}

int main ()
{
    std::istringstream file( R"(
<metObsSampleData xmlns="https://opendata.smhi.se/xsd/metobs_v1.xsd">
    <updated>2018-06-12T15:00:00.000Z</updated>
    <parameter>
        <key>21</key>
        <name>Byvind</name>
        <summary>max, 1 gang/tim</summary>
        <unit>metre per second</unit>
    </parameter>
    <station>
        <key>77210</key>
        <name>Olands Norra Udde A</name>
        <owner>SMHI</owner>
        <height>10.0</height>
    </station>
    <period>
        <key>latest-hour</key>
        <from>2018-06-12T14:00:01.000Z</from>
        <to>2018-06-12T15:00:00.000Z</to>
        <summary>Data fran senaste timmen</summary>
        <sampling>1 timme</sampling>
    </period>
    <position>
        <from>1995-08-01T00:00:00.000Z</from>
        <to>2018-06-12T15:00:00.000Z</to>
        <height>2.0</height>
        <latitude>57.3672</latitude>
        <longitude>17.0986</longitude>
    </position>
    <link rel="data" type="application/json" href="https://opendata-download-metobs.smhi.se/api/version/latest/parameter/21/station/77210/period/latest-hour/data.json"/>
    <link rel="data" type="application/xml" href="https://opendata-download-metobs.smhi.se/api/version/latest/parameter/21/station/77210/period/latest-hour/data.xml"/>
    <link rel="data" type="text/plain" href="https://opendata-download-metobs.smhi.se/api/version/latest/parameter/21/station/77210/period/latest-hour/data.csv"/>
    <link rel="period" type="application/atom+xml" href="https://opendata-download-metobs.smhi.se/api/version/latest/parameter/21/station/77210/period/latest-hour.atom"/>
    <link rel="iso19139" type="application/vnd.iso.19139+xml" href="https://opendata-catalog.smhi.se/catalog/srv/eng/csw?request=GetRecordById&service=CSW&version=2.0.2&elementSetName=full&outputSchema=csw:IsoRecord&id=25080190-38ba-4279-a65d-d9ef8d0bf949"/>
    <link rel="iso19139" type="application/vnd.iso.19139+xml" href="https://opendata-catalog.smhi.se/catalog/srv/eng/csw?request=GetRecordById&service=CSW&version=2.0.2&elementSetName=full&outputSchema=csw:IsoRecord&id=617a59fa-087b-4416-83df-486b85dcb1ed"/>
    <value>
        <date>2018-06-12T15:00:00.000Z</date>
        <value>2.8</value>
        <quality>Y</quality>
    </value>
</metObsSampleData>
                                )"
                           ) ;

    const double value = extract_value(file) ;

    if( !std::isnan(value) ) std::cout << "extracted value == " << value << '\n' ;
} 

http://coliru.stacked-crooked.com/a/c0dcd08e2f99169e
you can nest what repeater offered a little, if you need to find tag a followed by tag b ... etc value before end of tag a. If it becomes too complex, you can try other ideas but at some point, for complex files, you do end up needing to parse it for real. Just have to ask yourself how much trouble you are willing to go to before doing a full parse.
I am not sure how different rapidxml is to what i suggest, but if you are already using boost, you could use property trees.
Syntax is:
1
2
3
4
pt::ptree xml_resource;
std::ifstream ifs("file.xml");
pt::read_xml(ifs,xml_resource);
int this_value = file_resource.get<int>("path.to.value");
Hello!

Thank you guys for all your help

After some tought, and for future use, i did finally succeed with tinyxml.

If i did not go that route, the boost alternative seems to be the easiest.

My biggest problem were to little knowledge about the XML-"system"

Thanks again!
Topic archived. No new replies allowed.