~ubuntu-branches/ubuntu/trusty/xpathselect/trusty

« back to all changes in this revision

Viewing changes to lib/xpathselect.cpp

  • Committer: Package Import Robot
  • Author(s): Automatic PS uploader
  • Date: 2013-01-23 00:00:59 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130123000059-ez6oz726vueubmlj
Tags: 1.1.3daily13.01.23-0ubuntu1
Automatic snapshot from revision 28

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
#include <vector>
19
19
#include <queue>
20
 
#include <boost/algorithm/string.hpp>
21
 
#include <boost/algorithm/string/split.hpp>
22
 
#include <boost/algorithm/string/classification.hpp>
23
 
#include <boost/algorithm/string/predicate.hpp>
24
 
#include <boost/bind.hpp>
25
20
 
26
21
#include "xpathselect.h"
 
22
#include "xpathquerypart.h"
 
23
#include "parser.h"
27
24
 
28
25
namespace xpathselect
29
26
{
30
27
    // anonymous namespace for internal-only utility class:
31
28
    namespace
32
29
    {
33
 
        // Stores a part of an XPath query.
34
 
        class XPathQueryPart
35
 
        {
36
 
        public:
37
 
            enum class QueryPartType {Normal, Search};
38
 
            XPathQueryPart(std::string const& query_part)
39
 
            {
40
 
                type_ = (query_part == "") ? QueryPartType::Search :  QueryPartType::Normal;
41
 
 
42
 
                std::vector<std::string> part_pieces;
43
 
                boost::algorithm::split(part_pieces,
44
 
                    query_part,
45
 
                    boost::algorithm::is_any_of("[]="),
46
 
                    boost::algorithm::token_compress_on);
47
 
 
48
 
                // Boost's split() implementation does not match it's documentation! According to the
49
 
                // docs, it's not supposed to add empty strings, but it does, which is a PITA. This
50
 
                // next line removes them:
51
 
                part_pieces.erase( std::remove_if( part_pieces.begin(),
52
 
                    part_pieces.end(),
53
 
                    boost::bind( &std::string::empty, _1 ) ),
54
 
                  part_pieces.end());
55
 
 
56
 
                if (part_pieces.size() == 1)
57
 
                {
58
 
                    node_name_ = part_pieces.at(0);
59
 
                }
60
 
                else if (part_pieces.size() == 3)
61
 
                {
62
 
                    node_name_ = part_pieces.at(0);
63
 
                    param_name_ = part_pieces.at(1);
64
 
                    param_value_ = part_pieces.at(2);
65
 
                }
66
 
                else
67
 
                {
68
 
                    // assume it's just a node name:
69
 
                    node_name_ = query_part;
70
 
                }
71
 
            }
72
 
 
73
 
            bool Matches(Node::Ptr const& node) const
74
 
            {
75
 
                bool matches = (node_name_ == "*" || node->GetName() == node_name_);
76
 
                if (!param_name_.empty())
77
 
                {
78
 
                    matches &= node->MatchProperty(param_name_, param_value_);
79
 
                }
80
 
 
81
 
                return matches;
82
 
            }
83
 
 
84
 
            QueryPartType Type() const { return type_; }
85
 
 
86
 
        private:
87
 
            std::string node_name_;
88
 
            std::string param_name_;
89
 
            std::string param_value_;
90
 
            QueryPartType type_;
91
 
        };
92
 
 
93
 
        typedef std::vector<XPathQueryPart> QueryList;
94
 
 
95
30
        QueryList GetQueryPartsFromQuery(std::string const& query)
96
31
        {
 
32
            xpathselect::parser::xpath_grammar<std::string::const_iterator> grammar;
97
33
            QueryList query_parts;
98
34
 
99
 
            // split query into parts
100
 
            std::list<std::string> query_strings;
101
 
            boost::algorithm::split(query_strings,
102
 
                query,
103
 
                boost::algorithm::is_any_of("/"),
104
 
                boost::algorithm::token_compress_off);
105
 
 
106
 
            for(std::string part : query_strings)
 
35
            auto begin = query.cbegin();
 
36
            auto end = query.cend();
 
37
            if (boost::spirit::qi::parse(begin, end, grammar, query_parts) && (begin == end))
107
38
            {
108
 
                query_parts.push_back(XPathQueryPart(part));
 
39
                return query_parts;
109
40
            }
110
 
 
111
 
            // bost::split leaves the initial token in the output list, so we ignore the
112
 
            // first search token:
113
 
            if (query_parts.front().Type() == XPathQueryPart::QueryPartType::Search)
114
 
                query_parts.erase(query_parts.begin());
115
 
 
116
 
            return query_parts;
 
41
            return QueryList();
117
42
        }
118
43
 
119
44
        // Starting at each node listed in 'start_points', search the tree for nodes that match
154
79
        {
155
80
            query = "/" + root->GetName();
156
81
        }
157
 
        // sanity checking some obvious invalid queries:
158
 
        if (boost::algorithm::ends_with(query, "//"))
 
82
 
 
83
        QueryList query_parts = GetQueryPartsFromQuery(query);
 
84
        if (query_parts.empty())
159
85
            return NodeList();
160
 
 
161
 
        QueryList query_parts = GetQueryPartsFromQuery(query);
162
 
 
163
86
        auto query_part = query_parts.cbegin();
164
87
        NodeList start_nodes { root };
165
88
        while (query_part != query_parts.cend())