equal
deleted
inserted
replaced
108 return L""; |
108 return L""; |
109 } |
109 } |
110 } |
110 } |
111 |
111 |
112 xmlpp::Element* findSingleElement(const xmlpp::NodeSet& nodeset) { |
112 xmlpp::Element* findSingleElement(const xmlpp::NodeSet& nodeset) { |
|
113 // TODO: Allow multiple elements and attributes and wrap them? Like in relpipe-in-xmltable --raw-xml-attribute-wrapper --raw-xml-nodelist-wrapper |
113 if (nodeset.empty()) return nullptr; |
114 if (nodeset.empty()) return nullptr; |
114 else if (nodeset.size() > 1) throw std::invalid_argument("XPath should find one or zero elements."); |
115 else if (nodeset.size() > 1) throw std::invalid_argument("XPath should find one or zero elements."); |
115 else if (xmlpp::Element * element = dynamic_cast<xmlpp::Element*> (nodeset[0])) return element; |
116 else if (xmlpp::Element * element = dynamic_cast<xmlpp::Element*> (nodeset[0])) return element; |
116 else if (nodeset[0]->get_path() == "/") return findSingleElement(nodeset[0]->find("*")); // support also "/" not only "/*" expressions (return root element in both cases) |
117 else if (nodeset[0]->get_path() == "/") return findSingleElement(nodeset[0]->find("*")); // support also "/" not only "/*" expressions (return root element in both cases) |
117 else throw std::invalid_argument("XPath should find an element, not other kinds of nodes."); |
118 else throw std::invalid_argument("XPath should find an element, not other kinds of nodes."); |
168 } else { |
169 } else { |
169 if (isPrependingInputAttributes()) copyInputAttributesToOutput(); |
170 if (isPrependingInputAttributes()) copyInputAttributesToOutput(); |
170 for (auto oa : currentRelationConfiguration->outputAttributes) currentWriterMetadata.push_back({oa.name, oa.type}); |
171 for (auto oa : currentRelationConfiguration->outputAttributes) currentWriterMetadata.push_back({oa.name, oa.type}); |
171 if (isAppendingInputAttributes()) copyInputAttributesToOutput(); |
172 if (isAppendingInputAttributes()) copyInputAttributesToOutput(); |
172 |
173 |
|
174 // TODO: better metadata structure |
|
175 // TODO: optional namespaces |
173 dom.create_root_node("relpipe-tr-xpath"); |
176 dom.create_root_node("relpipe-tr-xpath"); |
174 dom.get_root_node()->add_child("relation-name")->add_child_text(s2x(name)); |
177 dom.get_root_node()->add_child("relation-name")->add_child_text(s2x(name)); |
175 resetRecordElement(); |
178 resetRecordElement(); |
176 } |
179 } |
177 |
180 |
192 xmlpp::DomParser attributeParser; |
195 xmlpp::DomParser attributeParser; |
193 attributeParser.parse_memory(s2x(value)); |
196 attributeParser.parse_memory(s2x(value)); |
194 attributeElement->import_node(attributeParser.get_document()->get_root_node(), true); |
197 attributeElement->import_node(attributeParser.get_document()->get_root_node(), true); |
195 } |
198 } |
196 } else { |
199 } else { |
|
200 // TODO: better boolean mapping? Missing text node will be evaluated as false(), however the expression still had to be "someAttribute/text()" because "someAttribute" will be evaluated as true() because the "someAttribute" element is present. |
197 attributeElement->add_child_text(s2x(value)); |
201 attributeElement->add_child_text(s2x(value)); |
198 } |
202 } |
199 |
203 |
200 if (currentAttributeIndex == 0) { |
204 if (currentAttributeIndex == 0) { |
201 recordElement->set_attribute("number", std::to_string(currentRecordNumber)); |
205 recordElement->set_attribute("number", std::to_string(currentRecordNumber)); |