| 523 | } |
| 524 | |
| 525 | std::string MzMLSpectrumDecoder::domParseString_(const std::string& in, std::vector<BinaryData>& data) |
| 526 | { |
| 527 | // PRECONDITON is below (since we first need to do XML parsing before validating) |
| 528 | // initializer list of XMLCh (= usually some type that fits utf16) from ASCII chars |
| 529 | static constexpr XMLCh id_tag[] = {'i','d', 0}; |
| 530 | static constexpr XMLCh default_array_length_tag[] = { 'd','e','f','a','u','l','t','A','r','r','a','y','L','e','n','g','t','h', 0}; |
| 531 | static constexpr XMLCh binary_data_array_tag[] = { 'b','i','n','a','r','y','D','a','t','a','A','r','r','a','y', 0}; |
| 532 | |
| 533 | //------------------------------------------------------------- |
| 534 | // Create parser from input string using MemBufInputSource |
| 535 | //------------------------------------------------------------- |
| 536 | xercesc::MemBufInputSource myxml_buf(reinterpret_cast<const unsigned char*>(in.c_str()), in.length(), "myxml (in memory)"); |
| 537 | std::unique_ptr<xercesc::XercesDOMParser> parser = std::make_unique<xercesc::XercesDOMParser>(); // make sure it is deleted even in case of exceptions |
| 538 | parser->setDoNamespaces(false); |
| 539 | parser->setDoSchema(false); |
| 540 | parser->setLoadExternalDTD(false); |
| 541 | parser->parse(myxml_buf); |
| 542 | |
| 543 | //------------------------------------------------------------- |
| 544 | // Start parsing |
| 545 | // see http://www.yolinux.com/TUTORIALS/XML-Xerces-C.html |
| 546 | //------------------------------------------------------------- |
| 547 | |
| 548 | // no need to free this pointer - owned by the parent parser object |
| 549 | xercesc::DOMDocument* doc = parser->getDocument(); |
| 550 | // Get the top-level element (needs to be <spectrum> or <chromatogram>) |
| 551 | xercesc::DOMElement* elementRoot = doc->getDocumentElement(); |
| 552 | if (!elementRoot) |
| 553 | { |
| 554 | throw Exception::ParseError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, in, "No root element"); |
| 555 | } |
| 556 | |
| 557 | OPENMS_PRECONDITION(xercesc::XMLString::equals(elementRoot->getTagName(), CONST_XMLCH("spectrum")) || xercesc::XMLString::equals(elementRoot->getTagName(), CONST_XMLCH("chromatogram")), |
| 558 | (String("The input needs to contain a <spectrum> or <chromatogram> tag as root element. Got instead '") + |
| 559 | String(Internal::unique_xerces_ptr(xercesc::XMLString::transcode(elementRoot->getTagName())).get()) + String("'.")).c_str()) |
| 560 | |
| 561 | // defaultArrayLength is a required attribute for the spectrum and the |
| 562 | // chromatogram tag (but still check for it first to be safe). |
| 563 | if (elementRoot->getAttributeNode(default_array_length_tag) == nullptr) |
| 564 | { |
| 565 | throw Exception::ParseError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, |
| 566 | in, "Root element does not contain defaultArrayLength XML tag."); |
| 567 | } |
| 568 | int default_array_length = xercesc::XMLString::parseInt(elementRoot->getAttribute(default_array_length_tag)); |
| 569 | OpenMS::Internal::StringManager sm; |
| 570 | std::string id = sm.convert(elementRoot->getAttribute(id_tag)); |
| 571 | |
| 572 | // Extract the binaryDataArray elements (there may be multiple) and process them |
| 573 | xercesc::DOMNodeList* li = elementRoot->getElementsByTagName(binary_data_array_tag); |
| 574 | for (Size i = 0; i < li->getLength(); i++) |
| 575 | { |
| 576 | // Will append one single BinaryData object to data |
| 577 | handleBinaryDataArray_(li->item(i), data); |
| 578 | |
| 579 | // Set the size correctly (otherwise MzMLHandlerHelper complains). |
| 580 | data.back().size = default_array_length; |
| 581 | } |
| 582 | |