void lclProcessAttribs( OStringBuffer& rBuffer, constchar* pcBeg, constchar* pcEnd )
{ /* Map attribute names to char-pointer of all attributes. This map is used tofindmultipleoccurrencesofattributeswiththesamename.The
mapped pointers are used as map key in the next map below. */ typedef ::std::map< OString, constchar* > AttributeNameMap;
AttributeNameMap aAttributeNames;
/* Map the char-pointers of all attributes to the full attribute definition
string. This preserves the original order of the used attributes. */ typedef ::std::map< constchar*, OString > AttributeDataMap;
AttributeDataMap aAttributes;
bool bOk = true; constchar* pcNameBeg = pcBeg; while( bOk && (pcNameBeg < pcEnd) )
{ // pcNameBeg points to begin of attribute name, find equality sign constchar* pcEqualSign = lclFindCharacter( pcNameBeg, pcEnd, '=' );
bOk = (pcEqualSign < pcEnd); if (bOk)
{ // find end of attribute name (ignore whitespace between name and equality sign) constchar* pcNameEnd = lclTrimWhiteSpaceFromEnd( pcNameBeg, pcEqualSign );
bOk = (pcNameBeg < pcNameEnd); if( bOk )
{ // find begin of attribute value (must be single or double quote) constchar* pcValueBeg = lclFindNonWhiteSpace( pcEqualSign + 1, pcEnd );
bOk = (pcValueBeg < pcEnd) && ((*pcValueBeg == '\'') || (*pcValueBeg == '"')); if( bOk )
{ // find end of attribute value (matching quote character) constchar* pcValueEnd = lclFindCharacter( pcValueBeg + 1, pcEnd, *pcValueBeg );
bOk = (pcValueEnd < pcEnd); if( bOk )
{
++pcValueEnd;
OString aAttribName( pcNameBeg, static_cast< sal_Int32 >( pcNameEnd - pcNameBeg ) );
OString aAttribData( pcNameBeg, static_cast< sal_Int32 >( pcValueEnd - pcNameBeg ) ); // search for an existing attribute with the same name
AttributeNameMap::iterator aIt = aAttributeNames.find( aAttribName ); // remove its definition from the data map if( aIt != aAttributeNames.end() )
aAttributes.erase( aIt->second ); // insert the attribute into both maps
aAttributeNames[ aAttribName ] = pcNameBeg;
aAttributes[ pcNameBeg ] = aAttribData; // continue with next attribute (skip whitespace after this attribute)
pcNameBeg = pcValueEnd; if( pcNameBeg < pcEnd )
{
bOk = lclIsWhiteSpace( *pcNameBeg ); if( bOk )
pcNameBeg = lclFindNonWhiteSpace( pcNameBeg + 1, pcEnd );
}
}
}
}
}
}
// if no error has occurred, build the resulting attribute list if( bOk ) for (autoconst& attrib : aAttributes)
rBuffer.append( " " + attrib.second ); // on error, just append the complete passed string else
lclAppendToBuffer( rBuffer, pcBeg, pcEnd );
}
void lclProcessElement( OStringBuffer& rBuffer, const OString& rElement )
{ // check that passed string starts and ends with the brackets of an XML element
sal_Int32 nElementLen = rElement.getLength(); if( nElementLen == 0 ) return;
// check start elements and simple elements for repeated attributes elseif( pcOpen[ 1 ] != '/' )
{ // find positions of text content inside brackets, exclude '/' in '<simpleelement/>' constchar* pcContentBeg = pcOpen + 1; bool bIsEmptyElement = pcClose[ -1 ] == '/'; constchar* pcContentEnd = bIsEmptyElement ? (pcClose - 1) : pcClose; // append opening bracket and element name to buffer constchar* pcWhiteSpace = lclFindWhiteSpace( pcContentBeg, pcContentEnd );
lclAppendToBuffer( rBuffer, pcOpen, pcWhiteSpace ); // find begin of attributes, and process all attributes constchar* pcAttribBeg = lclFindNonWhiteSpace( pcWhiteSpace, pcContentEnd ); if( pcAttribBeg < pcContentEnd )
lclProcessAttribs( rBuffer, pcAttribBeg, pcContentEnd ); // close the element if( bIsEmptyElement )
rBuffer.append( '/' );
rBuffer.append( '>' );
}
// append end elements without further processing else
{
rBuffer.append( rElement );
}
}
bool lclProcessCharacters( OStringBuffer& rBuffer, const OString& rChars )
{ /* MSO has a very weird way to store and handle whitespaces. The stream maycontainlotsofspaces,tabs,andnewlineswhichhavetobehandled assinglespacecharacter.Thiswillbedoneinthisfunction.
void InputStream::updateBuffer()
{ while( (mnBufferPos >= maBuffer.getLength()) && !mxTextStrm->isEOF() )
{ // collect new contents in a string buffer
OStringBuffer aBuffer;
// read and process characters until the opening bracket of the next XML element
OString aChars = readToElementBegin(); bool bHasOpeningBracket = lclProcessCharacters( aBuffer, aChars );
// read and process characters until (and including) closing bracket (an XML element)
OSL_ENSURE( bHasOpeningBracket || mxTextStrm->isEOF(), "InputStream::updateBuffer - missing opening bracket of XML element" ); if( bHasOpeningBracket && !mxTextStrm->isEOF() )
{ // read the element text (add the leading opening bracket manually)
OString aElement = "<" + readToElementEnd(); // check for CDATA part, starting with '<![CDATA[' if( aElement.match( gaOpeningCData ) )
{ // search the end tag ']]>' while( ((aElement.getLength() < gaClosingCData.getLength()) || !aElement.endsWith( gaClosingCData )) && !mxTextStrm->isEOF() )
aElement += readToElementEnd(); // copy the entire CDATA part
aBuffer.append( aElement );
} else
{ // no CDATA part - process the contents of the element
lclProcessElement( aBuffer, aElement );
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.