streamlet-examples/xpath.cpp
branchv_0
changeset 67 0766d298eb1c
parent 65 6944a03fb883
child 68 5d3d57d9c323
equal deleted inserted replaced
66:8a8b6434e4bb 67:0766d298eb1c
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    16  */
    16  */
    17 
    17 
    18 #include "streamlet-common.h"
    18 #include "streamlet-common.h"
    19 
    19 
       
    20 #include <unistd.h>
       
    21 #include <regex>
    20 #include <libxml++-2.6/libxml++/libxml++.h>
    22 #include <libxml++-2.6/libxml++/libxml++.h>
    21 
    23 
    22 class XPathStreamlet : public Streamlet {
    24 class XPathStreamlet : public Streamlet {
       
    25 private:
       
    26 	xmlpp::Node::PrefixNsMap ns;
       
    27 
       
    28 	void findXmlnsInEnvironment() {
       
    29 		std::regex xmlnsEnvPattern("xmlns_(.*)=(.*)");
       
    30 		std::cmatch match;
       
    31 		for (char **env = environ; *env; env++) if (std::regex_match(*env, match, xmlnsEnvPattern)) ns[std::string(match[1])] = match[2];
       
    32 	}
       
    33 
       
    34 	void findXmlnsInOptions() {
       
    35 		for (Option o : getOptions(std::wregex(L"xmlns[:_](.*)"))) ns[convertor.to_bytes(o.nameMatch[1])] = convertor.to_bytes(o.value);
       
    36 		for (Option o : getOptions(std::wregex(L"xmlns"), std::wregex(L"([^:]+):(.*)"))) ns[convertor.to_bytes(o.valueMatch[1])] = convertor.to_bytes(o.valueMatch[2]);
       
    37 	}
       
    38 
       
    39 	class XPathAttribute {
       
    40 	public:
       
    41 
       
    42 		std::wstring name;
       
    43 		std::wstring xpath;
       
    44 	};
       
    45 
       
    46 	std::vector<XPathAttribute> xpathAttributes;
       
    47 
       
    48 protected:
    23 
    49 
    24 	std::vector<AttributeMetadata> getOutputAttributesMetadata() override {
    50 	std::vector<AttributeMetadata> getOutputAttributesMetadata() override {
       
    51 		findXmlnsInEnvironment();
       
    52 		findXmlnsInOptions();
       
    53 
    25 		std::vector<AttributeMetadata> oam;
    54 		std::vector<AttributeMetadata> oam;
    26 		oam.push_back({getAlias(0, L"xpath"), L"string"});
    55 
       
    56 		std::vector<Option> attributeOptions = getOptions(L"attribute");
       
    57 		for (int i = 0, limit = attributeOptions.size(); i < limit; i++) {
       
    58 			std::wstring alias = getAlias(i, attributeOptions[i].value);
       
    59 			xpathAttributes.push_back({alias, attributeOptions[i].value});
       
    60 			oam.push_back({alias, STRING});
       
    61 		}
       
    62 
    27 		return oam;
    63 		return oam;
    28 	}
    64 	}
    29 
    65 
    30 	std::vector<OutputAttribute> getOutputAttributes() override {
    66 	std::vector<OutputAttribute> getOutputAttributes() override {
    31 		std::vector<OutputAttribute> oa;
    67 		std::vector<OutputAttribute> oa;
    32 
    68 
    33 		try {
    69 		try {
    34 			xmlpp::DomParser parser;
    70 			xmlpp::DomParser parser;
    35 			parser.parse_file(convertor.to_bytes(currentFile));
    71 			parser.parse_file(convertor.to_bytes(currentFile));
    36 			xmlpp::Element* root = parser.get_document()->get_root_node();
    72 			xmlpp::Element* root = parser.get_document()->get_root_node();
    37 			oa.push_back({L"XML OK", false});
    73 
    38 		} catch (...) {
    74 			for (XPathAttribute xpathAttribute : xpathAttributes) {
    39 			oa.push_back({L"invalid XML", true});
    75 				// TODO: support various modes like in XMLTableCommand
       
    76 				std::wstring result = convertor.from_bytes(root->eval_to_string(convertor.to_bytes(xpathAttribute.xpath), ns));
       
    77 				oa.push_back({result, false});
       
    78 			}
       
    79 		} catch (xmlpp::parse_error& e) {
       
    80 			for (XPathAttribute xpathAttribute : xpathAttributes) oa.push_back({L"", true});
       
    81 			// invalid XML → xmlpp::parse_error → just skip this file
       
    82 			// invalid XPath → xmlpp::exception → failure
    40 		}
    83 		}
       
    84 
    41 
    85 
    42 		return oa;
    86 		return oa;
    43 	}
    87 	}
    44 };
    88 };
    45 
    89