void DataDictionary::addXMLGroup( DOMDocument* pDoc, DOMNode* pNode, const std::string& msgtype, DataDictionary& DD, bool groupRequired ) { DOMAttributesPtr attrs = pNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("No name given to group"); int group = lookupXMLFieldNumber( pDoc, name ); int delim = 0; int field = 0; DataDictionary groupDD; DOMNodePtr node = pNode->getFirstChildNode(); while(node.get()) { if( node->getName() == "field" ) { field = lookupXMLFieldNumber( pDoc, node.get() ); groupDD.addField( field ); DOMAttributesPtr attrs = node->getAttributes(); std::string required; if( attrs->get("required", required) && ( required == "Y" || required =="y" ) && groupRequired ) { groupDD.addRequiredField(msgtype, field); } } else if( node->getName() == "component" ) { field = addXMLComponentFields( pDoc, node.get(), msgtype, groupDD, false ); } else if( node->getName() == "group" ) { field = lookupXMLFieldNumber( pDoc, node.get() ); groupDD.addField( field ); DOMAttributesPtr attrs = node->getAttributes(); std::string required; if( attrs->get("required", required ) && ( required == "Y" || required =="y" ) && groupRequired) { groupDD.addRequiredField(msgtype, field); } bool isRequired = false; if( attrs->get("required", required) ) isRequired = (required == "Y" || required == "y"); addXMLGroup( pDoc, node.get(), msgtype, groupDD, isRequired ); } if( delim == 0 ) delim = field; RESET_AUTO_PTR(node, node->getNextSiblingNode()); } if( delim ) DD.addGroup( msgtype, group, delim, groupDD ); }
int DataDictionary::addXMLComponentFields( DOMDocument* pDoc, DOMNode* pNode, const std::string& msgtype, DataDictionary& DD, bool componentRequired ) { int firstField = 0; DOMAttributesPtr attrs = pNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("No name given to component"); DOMNodePtr pComponentNode = pDoc->getNode("/fix/components/component[@name='" + name + "']"); if(pComponentNode.get() == 0) throw ConfigError("Component not found: " + name); DOMNodePtr pComponentFieldNode = pComponentNode->getFirstChildNode(); while(pComponentFieldNode.get()) { if(pComponentFieldNode->getName() == "field" || pComponentFieldNode->getName() == "group") { DOMAttributesPtr attrs = pComponentFieldNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("No name given to field"); int field = lookupXMLFieldNumber(pDoc, name); if( firstField == 0 ) firstField = field; std::string required; if(attrs->get("required", required) && (required == "Y" || required =="y") && componentRequired) { addRequiredField(msgtype, field); } DD.addField(field); DD.addMsgField(msgtype, field); } if(pComponentFieldNode->getName() == "component") { DOMAttributesPtr attrs = pComponentFieldNode->getAttributes(); std::string required; attrs->get("required", required); bool isRequired = (required == "Y" || required == "y"); addXMLComponentFields(pDoc, pComponentFieldNode.get(), msgtype, DD, isRequired); } if(pComponentFieldNode->getName() == "group") { DOMAttributesPtr attrs = pComponentFieldNode->getAttributes(); std::string required; attrs->get("required", required); bool isRequired = (required == "Y" || required == "y"); addXMLGroup(pDoc, pComponentFieldNode.get(), msgtype, DD, isRequired); } RESET_AUTO_PTR(pComponentFieldNode, pComponentFieldNode->getNextSiblingNode()); } return firstField; }
void DataDictionary::readFromDocument( DOMDocumentPtr pDoc ) throw( ConfigError ) { // VERSION DOMNodePtr pFixNode = pDoc->getNode("/fix"); if(!pFixNode.get()) throw ConfigError("Could not parse data dictionary file" ", or no <fix> node found at root"); DOMAttributesPtr attrs = pFixNode->getAttributes(); std::string type = "FIX"; if(attrs->get("type", type)) { if(type != "FIX" && type != "FIXT") throw ConfigError("type attribute must be FIX or FIXT"); } std::string major; if(!attrs->get("major", major)) throw ConfigError("major attribute not found on <fix>"); std::string minor; if(!attrs->get("minor", minor)) throw ConfigError("minor attribute not found on <fix>"); setVersion(type + "." + major + "." + minor); // FIELDS DOMNodePtr pFieldsNode = pDoc->getNode("/fix/fields"); if(!pFieldsNode.get()) throw ConfigError("<fields> section not found in data dictionary"); DOMNodePtr pFieldNode = pFieldsNode->getFirstChildNode(); if(!pFieldNode.get()) throw ConfigError("No fields defined"); while(pFieldNode.get()) { if(pFieldNode->getName() == "field") { DOMAttributesPtr attrs = pFieldNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("<field> does not have a name attribute"); std::string number; if(!attrs->get("number", number)) throw ConfigError("<field> " + name + " does not have a number attribute"); int num = atol(number.c_str()); std::string type; if(!attrs->get("type", type)) throw ConfigError("<field> " + name + " does not have a type attribute"); addField(num); addFieldType(num, XMLTypeToType(type)); addFieldName(num, name); DOMNodePtr pFieldValueNode = pFieldNode->getFirstChildNode(); while(pFieldValueNode.get()) { if(pFieldValueNode->getName() == "value") { DOMAttributesPtr attrs = pFieldValueNode->getAttributes(); std::string enumeration; if(!attrs->get("enum", enumeration)) throw ConfigError("<value> does not have enum attribute in field " + name); addFieldValue(num, enumeration); std::string description; if(attrs->get("description", description)) addValueName(num, enumeration, description); } RESET_AUTO_PTR(pFieldValueNode, pFieldValueNode->getNextSiblingNode()); } } RESET_AUTO_PTR(pFieldNode, pFieldNode->getNextSiblingNode()); } // HEADER if( type == "FIXT" || (type == "FIX" && major < "5") ) { DOMNodePtr pHeaderNode = pDoc->getNode("/fix/header"); if(!pHeaderNode.get()) throw ConfigError("<header> section not found in data dictionary"); DOMNodePtr pHeaderFieldNode = pHeaderNode->getFirstChildNode(); if(!pHeaderFieldNode.get()) throw ConfigError("No header fields defined"); while(pHeaderFieldNode.get()) { if(pHeaderFieldNode->getName() == "field" || pHeaderFieldNode->getName() == "group" ) { DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("<field> does not have a name attribute"); std::string required = "false"; attrs->get("required", required); addHeaderField(lookupXMLFieldNumber(pDoc.get(), name), required == "true"); } if(pHeaderFieldNode->getName() == "group") { DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes(); std::string required; attrs->get("required", required); bool isRequired = (required == "Y" || required == "y"); addXMLGroup(pDoc.get(), pHeaderFieldNode.get(), "_header_", *this, isRequired); } RESET_AUTO_PTR(pHeaderFieldNode, pHeaderFieldNode->getNextSiblingNode()); } } // TRAILER if( type == "FIXT" || (type == "FIX" && major < "5") ) { DOMNodePtr pTrailerNode = pDoc->getNode("/fix/trailer"); if(!pTrailerNode.get()) throw ConfigError("<trailer> section not found in data dictionary"); DOMNodePtr pTrailerFieldNode = pTrailerNode->getFirstChildNode(); if(!pTrailerFieldNode.get()) throw ConfigError("No trailer fields defined"); while(pTrailerFieldNode.get()) { if(pTrailerFieldNode->getName() == "field" || pTrailerFieldNode->getName() == "group" ) { DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("<field> does not have a name attribute"); std::string required = "false"; attrs->get("required", required); addTrailerField(lookupXMLFieldNumber(pDoc.get(), name), required == "true"); } if(pTrailerFieldNode->getName() == "group") { DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes(); std::string required; attrs->get("required", required); bool isRequired = (required == "Y" || required == "y"); addXMLGroup(pDoc.get(), pTrailerFieldNode.get(), "_trailer_", *this, isRequired); } RESET_AUTO_PTR(pTrailerFieldNode, pTrailerFieldNode->getNextSiblingNode()); } } // MSGTYPE DOMNodePtr pMessagesNode = pDoc->getNode("/fix/messages"); if(!pMessagesNode.get()) throw ConfigError("<messages> section not found in data dictionary"); DOMNodePtr pMessageNode = pMessagesNode->getFirstChildNode(); if(!pMessageNode.get()) throw ConfigError("No messages defined"); while(pMessageNode.get()) { if(pMessageNode->getName() == "message") { DOMAttributesPtr attrs = pMessageNode->getAttributes(); std::string msgtype; if(!attrs->get("msgtype", msgtype)) throw ConfigError("<field> does not have a name attribute"); addMsgType(msgtype); std::string name; if(attrs->get("name", name)) addValueName( 35, msgtype, name ); DOMNodePtr pMessageFieldNode = pMessageNode->getFirstChildNode(); while( pMessageFieldNode.get() ) { if(pMessageFieldNode->getName() == "field" || pMessageFieldNode->getName() == "group") { DOMAttributesPtr attrs = pMessageFieldNode->getAttributes(); std::string name; if(!attrs->get("name", name)) throw ConfigError("<field> does not have a name attribute"); int num = lookupXMLFieldNumber(pDoc.get(), name); addMsgField(msgtype, num); std::string required; if(attrs->get("required", required) && (required == "Y" || required == "y")) { addRequiredField(msgtype, num); } } else if(pMessageFieldNode->getName() == "component") { DOMAttributesPtr attrs = pMessageFieldNode->getAttributes(); std::string required; attrs->get("required", required); bool isRequired = (required == "Y" || required == "y"); addXMLComponentFields(pDoc.get(), pMessageFieldNode.get(), msgtype, *this, isRequired); } if(pMessageFieldNode->getName() == "group") { DOMAttributesPtr attrs = pMessageFieldNode->getAttributes(); std::string required; attrs->get("required", required); bool isRequired = (required == "Y" || required == "y"); addXMLGroup(pDoc.get(), pMessageFieldNode.get(), msgtype, *this, isRequired); } RESET_AUTO_PTR(pMessageFieldNode, pMessageFieldNode->getNextSiblingNode()); } } RESET_AUTO_PTR(pMessageNode, pMessageNode->getNextSiblingNode()); } }