23#include <QXmlStreamAttributes>
39namespace DocumentsReader {
49 m_elementPointerHasBeenReturned(false),
51 m_addAbsoluteOffsetToTokens(true)
55 LDEBUG <<
"StructuredDocumentXMLParser::StructuredDocumentXMLParser()";
67 LDEBUG <<
"StructuredDocumentXMLParser::setShiftFrom";
69 m_shiftFrom = shiftFrom;
78 LDEBUG <<
"StructuredDocumentXMLParser::init(): readPropertiesMetadata ...";
80 readPropertiesMetadata ( unitConfiguration ) ;
83 vector<pair<QString,FieldType> > fields;
87 LDEBUG <<
"StructuredDocumentXMLParser::init(): readFieldTags " << f;
89 readFieldTags ( unitConfiguration,
static_cast<FieldType> ( f ),fields );
92 for ( vector<pair<QString,FieldType> >::const_iterator tag=fields.begin();
93 tag!=fields.end(); tag++ )
96 LDEBUG <<
"StructuredDocumentXMLParser::init(): addField "
97 << ( *tag ).first <<
" to list of type " << ( *tag ).second;
99 addField ( ( *tag ).first, ( *tag ).second );
105 LDEBUG <<
"StructuredDocumentXMLParser::init(): getMapAtKey(specialCharacterSize)";
109 const map<string,string>& specialCharSizeMap=unitConfiguration.
110 getMapAtKey (
"specialCharacterSize" );
111 map<string,string>::const_iterator
112 it=specialCharSizeMap.begin(),
113 it_end=specialCharSizeMap.end();
114 for ( ; it!=it_end; it++ )
116 m_specialCharacterSize[ ( *it ).first[0]]=atoi ( ( *it ).second.c_str() );
122 LWARN <<
"StructuredDocumentXMLParser::init: no such map specialCharacterSize";
129 m_addAbsoluteOffsetToTokens =
false;
134 LINFO <<
"StructuredDocumentXMLParser: No parameter addAbsoluteOffsetToTokens. Using default 'yes'";
138 LDEBUG <<
"StructuredDocumentXMLParser::init() done";
144bool StructuredDocumentXMLParser::
147 return ( m_specialCharacterSize.find ( c )
148 != m_specialCharacterSize.end() );
151unsigned int StructuredDocumentXMLParser::
154 return m_specialCharacterSize[c];
158void StructuredDocumentXMLParser::readPropertiesMetadata (
168 deque<string> standardPropertyList = groupConf.
getListsValueAtKey (
"standard-properties-list" );
170 for ( deque<string>::const_iterator attributeIdentifier = standardPropertyList.begin();
171 attributeIdentifier != standardPropertyList.end(); attributeIdentifier++ )
176 const std::deque<QString> elementTagSet = attr.getElementTagNames();
177 for ( std::deque<QString>::const_iterator it = elementTagSet.begin() ;
178 it != elementTagSet.end() ; it++ )
180 const QString elementTagName = *it;
181 auto ite = m_elementTag2DocumentPropertyType.find( elementTagName );
182 if( ite != m_elementTag2DocumentPropertyType.end() ){
183 if( ite->second.getId() != attr.getId() ) {
185 LWARN <<
"ElementTag" << elementTagName <<
"cannot be used for"<< attr.getId() <<
", it is already used for Document Property" << ite->second.getId() <<
". Skip";
190 LDEBUG <<
"ElementTag" << elementTagName <<
"is used for property" << attr.getId();
192 m_elementTag2DocumentPropertyType.insert ( std::make_pair( elementTagName, attr ) );
195 const std::deque< std::pair<QString,QString> >& elementTagOfPairSet = attr.getAttributeTagNames();
196 for ( std::deque< std::pair<QString,QString> >::const_iterator it = elementTagOfPairSet.begin() ;
197 it != elementTagOfPairSet.end() ; it++ )
199 const QString elementTagName = (*it).first;
200 const QString attributeTagName = (*it).second;
201 const auto ite = m_elementTagOfPair2DocumentPropertyType.find( elementTagName );
202 if( ite != m_elementTagOfPair2DocumentPropertyType.end() ){
203 if( ite->second.getId() != attr.getId() ) {
205 LWARN <<
"ElementTag" << elementTagName <<
"AttributeTagName" << attributeTagName <<
"cannot be used for"<< attr.getId() <<
", it is already used for Document Property" << ite->second.getId() <<
". Skip";
210 LDEBUG <<
"ElementTag" << elementTagName <<
"AttributeTagName" << attributeTagName <<
"is used for property" << attr.getId();
212 m_elementTagOfPair2DocumentPropertyType.insert ( std::make_pair( elementTagName, attr ) );
219 LWARN <<
"StructuredDocumentXMLParser: NoSuchList Exception: standard-properties-list";
225 deque<string> extendedPropertyList= groupConf.
getListsValueAtKey (
"extended-properties-list" );
227 for ( deque<string>::const_iterator attributeIdentifier = extendedPropertyList.begin();
228 attributeIdentifier != extendedPropertyList.end(); attributeIdentifier++ )
233 const std::deque<QString> elementTagSet = attr.getElementTagNames();
234 for ( std::deque<QString>::const_iterator it = elementTagSet.begin() ;
235 it != elementTagSet.end() ; it++ )
237 const QString elementTagName = *it;
238 const auto ite = m_elementTag2DocumentPropertyType.find( elementTagName );
239 if( ite != m_elementTag2DocumentPropertyType.end() ){
240 if( ite->second.getId() != attr.getId() ) {
242 LWARN <<
"ElementTag" << elementTagName <<
"cannot be used for"<< attr.getId() <<
", it is already used for Document Property" << ite->second.getId() <<
". Skip";
247 LDEBUG <<
"ElementTag" << elementTagName <<
"is used for property" << attr.getId();
250 m_elementTag2DocumentPropertyType.insert ( std::make_pair( elementTagName, attr ) );
253 const std::deque< std::pair<QString,QString> > elementTagOfPairSet = attr.getAttributeTagNames();
254 for ( std::deque< std::pair<QString,QString> >::const_iterator it = elementTagOfPairSet.begin() ;
255 it != elementTagOfPairSet.end() ; it++ )
257 const QString elementTagName = (*it).first;
258 const QString attributeTagName = (*it).second;
259 const auto ite = m_elementTagOfPair2DocumentPropertyType.find( elementTagName );
260 if( ite != m_elementTagOfPair2DocumentPropertyType.end() ){
261 if( ite->second.getId() != attr.getId() ) {
263 LWARN <<
"ElementTag" << elementTagName <<
"AttributeTagName" << attributeTagName <<
"cannot be used for"<< attr.getId() <<
", it is already used for Document Property" << ite->second.getId() <<
". Skip";
268 LDEBUG <<
"ElementTag" << elementTagName <<
"AttributeTagName" << attributeTagName <<
"is used for property" << attr.getId();
270 m_elementTagOfPair2DocumentPropertyType.insert ( std::make_pair( elementTagName, attr ) );
277 LWARN <<
"StructuredDocumentXMLParser: NoSuchList Exception: extended-properties-list";
282void StructuredDocumentXMLParser::readFieldTags (
287 LDEBUG <<
"StructuredDocumentXMLParser::readFieldTags" << type;
289 QString errMess (
"" );
293 LDEBUG <<
"StructuredDocumentXMLParser::readFieldTags fieldTagListName:" << fieldTagListName;
299 deque<string> tagList= groupConf.
getListsValueAtKey ( fieldTagListName.toUtf8().constData() );
300 for ( deque<string>::const_iterator tag=tagList.begin();
301 tag!=tagList.end(); tag++ )
303 fields.push_back ( make_pair ( QString::fromUtf8(tag->c_str()),type ) );
308 errMess = QString (
"NoSuchGroup Exception: tagSemantic" );
313 errMess = QString (
"NoSuchList Exception: " ) +fieldTagListName;
316 if ( errMess.compare (
"" ) )
320 LWARN <<
"DocumentReader: " << errMess;
329 LDEBUG <<
"StructuredDocumentXMLParser::addField" << fieldName << type;
332 int spaceOffset=fieldName.indexOf (
' ' );
333 if ( spaceOffset == -1 )
335 m_fields.insert ( std::pair<QString,FieldTypeElement> ( fieldName,FieldTypeElement ( type ) ) );
339 int equalOffset=fieldName.indexOf (
'=',spaceOffset+1 );
340 QString attributeName ( fieldName.mid(spaceOffset+1,equalOffset-spaceOffset-1) );
341 QString newFieldName ( fieldName.left(spaceOffset) );
343 m_fields.insert ( std::pair<QString,FieldTypeElement> ( newFieldName,FieldTypeElement ( type,attributeName ) ) );
354 LDEBUG <<
"StructuredDocumentXMLParser: startDocument()";
360 QString rootName (
"ROOT" );
361 m_currentDocument->pushHierarchyChild ( rootName, m_shiftFrom->correct_offset(0, parserOffset), noProperty );
362 setCurrentByteOffset ( parserOffset );
370 LDEBUG <<
"StructuredDocumentXMLParser: endDocument()";
394 LDEBUG <<
"StructuredDocumentXMLParser::startElement(" << name << parserOffset <<
"), document.size="
395 << m_currentDocument->size();
406 assert(!m_currentDocument->empty());
411 if ( isMetaData ( name ) )
414 LDEBUG <<
"StructuredDocumentXMLParser::startElement: " << name <<
" is metadata" ;
417 propType = getMetaDataFromName ( name );
427 LDEBUG <<
"StructuredDocumentXMLParser::startElement: current" << currentElement->
getElementName() <<
"is discardable, discards element " << name;
429 newElement = m_currentDocument->pushDiscardableChild ( name, parserOffset );
434 LDEBUG <<
"StructuredDocumentXMLParser::startElement: current" << currentElement->
getElementName() <<
"is indexing";
438 if ( isDiscardable ( name ) )
441 LDEBUG <<
"StructuredDocumentXMLParser::startElement:" << name <<
"discardable element" ;
444 newElement = m_currentDocument->pushDiscardableChild ( name, parserOffset );
449 LDEBUG <<
"StructuredDocumentXMLParser::startElement:" << name <<
"presentation element" ;
451 newElement = m_currentDocument->pushPresentationChild ( name, parserOffset );
458 LDEBUG <<
"StructuredDocumentXMLParser::startElement: current" << currentElement->
getElementName() <<
"is hierarchy";
460 if ( isHierarchy ( name ) )
463 LDEBUG <<
"StructuredDocumentXMLParser::startElement: " << name <<
"hierarchy element" ;
466 newElement = m_currentDocument->pushHierarchyChild ( name, m_shiftFrom->correct_offset(0, parserOffset), propType );
469 else if ( isIndexing ( name ) )
472 LDEBUG <<
"StructuredDocumentXMLParser::startElement: " << name <<
"indexing element" ;
474 newElement = m_currentDocument->pushIndexingChild ( name, parserOffset, propType );
480 LDEBUG <<
"StructuredDocumentXMLParser::startElement: " << name <<
"ignored element" ;
482 newElement = m_currentDocument->pushIgnoredChild ( name, parserOffset, propType );
488 LDEBUG <<
"StructuredDocumentXMLParser::startElement: current" << currentElement->
getElementName() <<
"is presentation";
490 if ( isDiscardable ( name ) )
493 LDEBUG <<
"StructuredDocumentXMLParser::startElement: " << name <<
" is discardable " ;
496 newElement = m_currentDocument->pushDiscardableChild ( name, parserOffset );
501 newElement = m_currentDocument->pushPresentationChild ( name, parserOffset );
507 LDEBUG <<
"StructuredDocumentXMLParser::startElement: current" << currentElement->
getElementName() <<
"is ignored. Ignoring also" << name;
509 newElement = m_currentDocument->pushIgnoredChild ( name, parserOffset, propType );
513 LDEBUG <<
"StructuredDocumentXMLParser::startElement: all inheritance cases are handled for current" << currentElement->
getElementName() <<
". We should not get here while handling" << name;
520 assert ( newElement );
527 LDEBUG <<
"StructuredDocumentXMLParser::startElement: " << name <<
" has metadata";
529 auto range = m_elementTagOfPair2DocumentPropertyType.equal_range ( name );
531 for (
auto propIt = range.first ; propIt != range.second ; ( propIt ) ++ )
535 LDEBUG <<
"StructuredDocumentXMLParser::startElement: try " << propType.
getId();
538 for (
auto namesIt = attrAndElementNames.begin(); namesIt != attrAndElementNames.end() ; namesIt++ )
540 if ( ! ( *namesIt ).first.compare ( name ) )
543 QString attributeName = (*namesIt ).second;
547 LDEBUG <<
"StructuredDocumentXMLParser::startElement: found " << ( *namesIt ).first
548 <<
" as element with attribute " << ( *namesIt ).second
549 <<
" and value " << utf8Value;
551 m_currentDocument->setDataToLastElement ( propType, utf8Value, m_processor );
558 LDEBUG <<
"StructuredDocumentXMLParser::startElement() end";
564 const QString& qsname,
565 const QString& qName ,
566 unsigned int parserOffset)
576 LDEBUG <<
"StructuredDocumentXMLParser::endElement" << qsname << parserOffset
585 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop discardable element " << qsname;
587 m_currentDocument->popDiscardableElement(parserOffset);
589 LDEBUG <<
"StructuredDocumentXMLParser::endElement(" << qsname
590 <<
"), document.size = " << m_currentDocument->size() <<
" before return";
596 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop indexing element " << qsname;
597 assert(currentElement->size() > 0);
601 m_processor->
handle(*m_currentDocument, currentElement->front()->getText(),
602 m_addAbsoluteOffsetToTokens ? currentElement->front()->
getOffset() : 0,
603 qsname.toUtf8().constData());
608 LERROR <<
"StructuredDocumentXMLParser::endElement: error while handling indexing element"
609 << qsname <<
"absolute offset:" << currentElement->front()->
getOffset() <<
". The content will be ignored.";
613 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop indexing element handled" << qsname;
617 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop indexing element ended" << qsname;
619 m_currentDocument->popIndexingElement(parserOffset);
621 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop indexing element poped" << qsname;
627 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop hierarchy element " << qsname;
630 m_currentDocument->popHierarchyElement(parserOffset);
635 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop presentation element " << qsname;
637 m_currentDocument->popPresentationElement ( parserOffset );
639 LDEBUG <<
"StructuredDocumentXMLParser::endElement(" << qsname <<
"), document.size = "
640 << m_currentDocument->size() <<
" before return";
646 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop property element " << qsname;
649 m_currentDocument->setDataToElement(currentElement, currentElement->
getPropType(), currentElement->back()->getText().toUtf8().constData(), m_processor);
650 m_currentDocument->popPropertyElement( parserOffset );
652 LDEBUG <<
"StructuredDocumentXMLParser::endElement(" << qsname <<
"), document.size = "
653 << m_currentDocument->size() <<
" before return";
659 LDEBUG <<
"StructuredDocumentXMLParser::endElement: pop ignored element " << qsname;
662 m_currentDocument->setDataToElement(currentElement, currentElement->
getPropType(), currentElement->back()->getText().toUtf8().constData(), m_processor);
663 m_currentDocument->popIgnoredElement ( parserOffset );
665 LDEBUG <<
"StructuredDocumentXMLParser::endElement(" << qsname <<
"), document.size = "
666 << m_currentDocument->size() <<
" before return";
673 LERROR <<
"All inheritance cases are handled. We should not get here";
685void StructuredDocumentXMLParser::setCurrentByteOffset (
const unsigned int offset )
689 LDEBUG <<
"StructuredDocumentXMLParser::setCurrentByteOffset(" << offset <<
")";
693 if ( m_currentDocument->size() != 0 )
702 unsigned int parserOffset)
707 LDEBUG <<
"StructuredDocumentXMLParser::characters" << value.left(50)
708 <<
"(...), length=" << value.size() <<
", parserOffset=" << parserOffset;
710 auto currentElement = m_currentDocument->back();
711 currentElement->setOffset(parserOffset);
712 if ( !value.isEmpty() )
715 if ( m_shiftFrom->contains(parserOffset) && isSpecialCharacter ( firstChar ) )
718 LDEBUG <<
"StructuredDocumentXMLParser::characters m_shiftFrom:";
719 LDEBUG <<
"StructuredDocumentXMLParser::characters: first char "
720 << firstChar <<
" is special character: add "
721 << getSpecialCharSize ( firstChar )-1 <<
" spaces";
724 value.insert ( 1,spaces );
729 LDEBUG <<
"StructuredDocumentXMLParser::characters: first char "
730 << firstChar <<
"(" << firstChar
731 <<
") is not a special character";
734 currentElement->addToCurrentOffset ( value );
742 auto range=m_fields.equal_range ( elementName );
743 for (
auto it=range.first; it!=range.second; it++ )
745 if ( ( *it ).second.getType() == type )
753bool StructuredDocumentXMLParser::isHierarchy (
const QString& elementName )
const
758bool StructuredDocumentXMLParser::isIndexing (
const QString& elementName )
const
763bool StructuredDocumentXMLParser::isRoot (
const QString& elementName )
const
765 return isFieldType ( elementName,
NODE_ROOT );
768bool StructuredDocumentXMLParser::isDiscardable (
const QString& elementName )
const
776bool StructuredDocumentXMLParser::hasMetaData (
const QString& elementName )
const
778 auto range=m_elementTagOfPair2DocumentPropertyType.equal_range ( elementName );
780 if ( range.first != range.second )
793bool StructuredDocumentXMLParser::isMetaData (
const QString& elementName )
const
795 auto pos = m_elementTag2DocumentPropertyType.find ( elementName );
796 if ( pos != m_elementTag2DocumentPropertyType.end() )
807DocumentPropertyType StructuredDocumentXMLParser::getMetaDataFromName (
const QString& elementName )
const
810 auto pos = m_elementTag2DocumentPropertyType.find ( elementName );
811 if ( pos != m_elementTag2DocumentPropertyType.end() )
815 LDEBUG <<
"StructuredDocumentXMLParser::getMetaDataFromName(" << elementName <<
")="
816 << ( ( *pos ).second ).
getId();
818 return ( *pos ).second;
823 LWARN <<
"StructuredDocumentXMLParser::getMetaDataFromName: no property associated with element name "
825 return DocumentPropertyType();
Defines a Factory to create Object of type Base.
std::string & getParamsValueAtKey(const std::string &key)
std::deque< std::string > & getListsValueAtKey(const std::string &key)
return a message when a 'group' was not found
return a message when a 'list' was not found
return a message when a 'map' was not found
return a message when a 'param' was not found
virtual FieldType nodeType()
Element avec contenu texte.
unsigned long int getOffset()
virtual const QString & getElementName() const
void addSpaces(int nbSpaces)
virtual const DocumentPropertyType & getPropType()
Partie d'un document structure decodee avant analyse.
const std::deque< std::pair< QString, QString > > & getAttributeTagNames() const
const CardinalityType & getValueCardinality() const
XML parser for source structured documents.
StructuredDocumentXMLParser()
virtual ~StructuredDocumentXMLParser(void)
void init(Lima::Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
bool startDocument(unsigned int parserOffset)
bool characters(const QString &ch, unsigned int parserOffset)
bool endElement(const QString &namespaceURI, const QString &qsname, const QString &qName, unsigned int parserOffset)
void setShiftFrom(std::shared_ptr< const ShiftFrom > shiftFrom)
bool startElement(const QString &namespaceURI, const QString &name, const QString &qName, const QXmlStreamAttributes &attributes, unsigned int parserOffset)
Manage initialization of InitializableObjects using configuration module and parameters.
const std::string & getId() const
get the object id
static const DocumentsReaderResources & single()
const singleton accessor
virtual void startIndexing(const DocumentsReader::ContentStructuredDocument &contentDocument)=0
virtual void handle(const DocumentsReader::ContentStructuredDocument &contentDocument, const Lima::LimaString &text, unsigned long int offset, std::string langOfAnalysis)=0
virtual void endHierarchy(const DocumentsReader::ContentStructuredDocument &contentDocument)=0
virtual void endIndexing(const DocumentsReader::ContentStructuredDocument &contentDocument)=0
virtual void startHierarchy(const DocumentsReader::ContentStructuredDocument &contentDocument)=0
std::string limastring2utf8stdstring(const Lima::LimaString &phrase, uint32_t size0)
Convert a wide string to a string , in dest up to size bytes.
static const QString tagSemanticItem[MAX_NODE_TYPE]
FieldType
a type containing the type of an element
@ NODE_DISCARDABLE
root of XML file
@ NODE_PRESENTATION
node that can contain indexing nodes in its hierarchy.
@ NODE_ROOT
no type: field is ignored
@ NODE_INDEXING
node inside an indexing node whose content (including its children) is replaced by spaces
@ NODE_HIERARCHY
node whose content is analyzed and indexed
@ NODE_PROPERTY
nodes which are not children of hierarchy nodes are ignored
@ NODE_IGNORED
node inside an indexing node with content replaced by spaces, but which content is kept
Lima::SimpleFactory< AbstractReaderResource, Lima::DocumentsReader::StructuredDocumentXMLParser > structuredDocumentXMLParserFactory(STRUCTUREDDOCUMENTXMLPARSER_CLASSID)
#define STRUCTUREDDOCUMENTXMLPARSER_CLASSID