diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2011-12-02 17:38:51 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2011-12-07 14:47:11 +0100 |
commit | 7be8bac42aa578dc7f250a490634e13d1dac550b (patch) | |
tree | c9b51c1b92a6683d50277038549243cd59eed7d5 | |
parent | 1e4fb45c03e1787a6f73a93a1d9a68911d17a4e6 (diff) |
make the linear xml processing API more generic
I'm pretty sure I'll love to use it in writerfilter instead of the normal
API whenever I get the chance.
-rw-r--r-- | oox/inc/oox/mathml/importutils.hxx | 62 | ||||
-rw-r--r-- | oox/source/mathml/importutils.cxx | 2 | ||||
-rw-r--r-- | starmath/source/ooxmlimport.cxx | 4 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFastContextHandler.cxx | 58 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFastContextHandler.hxx | 42 |
5 files changed, 129 insertions, 39 deletions
diff --git a/oox/inc/oox/mathml/importutils.hxx b/oox/inc/oox/mathml/importutils.hxx index 9f759307b7b3..6906851e5091 100644 --- a/oox/inc/oox/mathml/importutils.hxx +++ b/oox/inc/oox/mathml/importutils.hxx @@ -41,15 +41,15 @@ namespace oox namespace formulaimport { +// used to differentiate between tags that opening or closing const int TAG_OPENING = 1 << 29; const int TAG_CLOSING = 1 << 30; -// used to differentiate between tags that open or close -// TODO -//inline int OPENING( int token ) { return TAG_OPENING | token; } -//inline int CLOSING( int token ) { return TAG_CLOSING | token; } -#define OPENING( token ) ( TAG_OPENING | token ) -#define CLOSING( token ) ( TAG_CLOSING | token ) +// you probably want to #define these to something shorter in the .cxx file, +// but they must be done as macros, otherwise they wouldn't be usable for case values, +// and macros cannot be namespaced +#define XML_STREAM_OPENING( token ) ( TAG_OPENING | token ) +#define XML_STREAM_CLOSING( token ) ( TAG_CLOSING | token ) /** Class for storing a stream of xml tokens. @@ -59,7 +59,55 @@ const int TAG_CLOSING = 1 << 30; files, unlike the usual LO way of using callbacks, context handlers and similar needlesly complicated stuff (YMMV). - @since 3.5.0 + The advantages of this approach is easy to read and debug code (as it is just functions + reading tokens one by one and calling other functions, compared to having to use callbacks + and temporary storage). The disadvantage is that the XML structure needs to be handled + manually by the code. + + Note that tag identifiers are simply int values and the API does not care besides matching + their values to XML stream contents and requiring that the values are not as high as TAG_OPENING. + Be prepared for the fact that some of the functions may throw exceptions if the input + stream does not match the required token (TBD). + + The API tries to make the common idioms as simple as possible, see the following examples. + + Parse <tagone attr="value"><tagtwo>text</tagtwo></tagone> , where tagtwo is optional: + @code +XmlStream::Tag tagoneTag = stream.ensureOpeningTag( tagone ); +if( attributeTag.hasAttribute( attr )) + ... = attributeTag.attribute( attr, defaultValueOfTheRightType ); +if( XmlStream::Tag tagtwoTag = stream.checkOpeningTag( tagtwo )) +{ + ... = tagtwoTag.text; + stream.ensureClosingTag( tagtwo ); +} +stream.ensureClosingTag( tagone ); + @endcode + + Parse an element that may contain several sub-elements of different types in random order: + @code +stream.ensureOpeningTag( element ); +while( !stream.atEnd() && stream.currentToken() != CLOSING( element )) + { + switch( stream.currentToken()) + { + case OPENING( subelement1 ): + handleSubElement1(); + break; + case OPENING( subelement2 ): + ... process subelement2; + break; + default: + stream.handleUnexpectedTag(); + break; + } +stream.ensureClosingTag( element ); + @endcode + + If there may be just a one type of sub-element, handle it directly without the switch statement. + If there may not be a zero number of sub-elements, use a helper bool variable or use a do-while loop. + + @since 3.5 */ class OOX_DLLPUBLIC XmlStream { diff --git a/oox/source/mathml/importutils.cxx b/oox/source/mathml/importutils.cxx index 61f04a97e716..2a7d19c9db07 100644 --- a/oox/source/mathml/importutils.cxx +++ b/oox/source/mathml/importutils.cxx @@ -41,6 +41,8 @@ #define STR( str ) OUString( RTL_CONSTASCII_USTRINGPARAM( str )) #define CSTR( str ) ( rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr()) +#define OPENING( token ) XML_STREAM_OPENING( token ) +#define CLOSING( token ) XML_STREAM_CLOSING( token ) // HACK - TODO convert to the real debug stuff #undef SAL_LOG_LEVEL diff --git a/starmath/source/ooxmlimport.cxx b/starmath/source/ooxmlimport.cxx index c776163de16a..73f0ea50b7dd 100644 --- a/starmath/source/ooxmlimport.cxx +++ b/starmath/source/ooxmlimport.cxx @@ -44,8 +44,8 @@ The primary internal data structure for the formula is the text representation */ #define M_TOKEN( token ) OOX_TOKEN( officeMath, token ) -#define OPENING_TAG( token ) OPENING( token ) -#define CLOSING_TAG( token ) CLOSING( token ) +#define OPENING( token ) XML_STREAM_OPENING( token ) +#define CLOSING( token ) XML_STREAM_CLOSING( token ) // *sigh* #define STR( str ) OUString( RTL_CONSTASCII_USTRINGPARAM( str )) diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx index 732391ce4cad..4b183b903063 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx @@ -2366,35 +2366,16 @@ Token_t OOXMLFastContextHandlerWrapper::getToken() const /* - class OOXMLFastContextHandlerMath + class OOXMLFastContextHandlerLinear */ -OOXMLFastContextHandlerMath::OOXMLFastContextHandlerMath(OOXMLFastContextHandler* pContext) +OOXMLFastContextHandlerLinear::OOXMLFastContextHandlerLinear(OOXMLFastContextHandler* pContext) : OOXMLFastContextHandlerProperties(pContext) , depthCount( 0 ) { } -void OOXMLFastContextHandlerMath::process() -{ - SvGlobalName name( SO3_SM_CLASSID ); - comphelper::EmbeddedObjectContainer container; - rtl::OUString aName; - uno::Reference< embed::XEmbeddedObject > ref = container.CreateEmbeddedObject( name.GetByteSequence(), aName ); - uno::Reference< uno::XInterface > component( ref->getComponent(), uno::UNO_QUERY ); - if( oox::FormulaImportBase* import = dynamic_cast< oox::FormulaImportBase* >( component.get())) - import->readFormulaOoxml( buffer ); - if (isForwardEvents()) - { - OOXMLPropertySet * pProps = new OOXMLPropertySetImpl(); - OOXMLValue::Pointer_t pVal( new OOXMLStarMathValue( ref )); - OOXMLProperty::Pointer_t pProp( new OOXMLPropertyImpl( NS_ooxml::LN_starmath, pVal, OOXMLPropertyImpl::ATTRIBUTE )); - pProps->add( pProp ); - mpStream->props( writerfilter::Reference< Properties >::Pointer_t( pProps )); - } -} - -void OOXMLFastContextHandlerMath::lcl_startFastElement(Token_t Element, +void OOXMLFastContextHandlerLinear::lcl_startFastElement(Token_t Element, const uno::Reference< xml::sax::XFastAttributeList >& Attribs) throw (uno::RuntimeException, xml::sax::SAXException) { @@ -2402,7 +2383,7 @@ void OOXMLFastContextHandlerMath::lcl_startFastElement(Token_t Element, ++depthCount; } -void OOXMLFastContextHandlerMath::lcl_endFastElement(Token_t Element) +void OOXMLFastContextHandlerLinear::lcl_endFastElement(Token_t Element) throw (uno::RuntimeException, xml::sax::SAXException) { buffer.appendClosingTag( Element ); @@ -2411,7 +2392,7 @@ void OOXMLFastContextHandlerMath::lcl_endFastElement(Token_t Element) } uno::Reference< xml::sax::XFastContextHandler > -OOXMLFastContextHandlerMath::lcl_createFastChildContext(Token_t, +OOXMLFastContextHandlerLinear::lcl_createFastChildContext(Token_t, const uno::Reference< xml::sax::XFastAttributeList >&) throw (uno::RuntimeException, xml::sax::SAXException) { @@ -2420,12 +2401,39 @@ OOXMLFastContextHandlerMath::lcl_createFastChildContext(Token_t, return xContextHandler; } -void OOXMLFastContextHandlerMath::lcl_characters(const ::rtl::OUString& aChars) +void OOXMLFastContextHandlerLinear::lcl_characters(const ::rtl::OUString& aChars) throw (uno::RuntimeException, xml::sax::SAXException) { buffer.appendCharacters( aChars ); } +/* + class OOXMLFastContextHandlerLinear + */ + +OOXMLFastContextHandlerMath::OOXMLFastContextHandlerMath(OOXMLFastContextHandler* pContext) + : OOXMLFastContextHandlerLinear(pContext) +{ +} + +void OOXMLFastContextHandlerMath::process() +{ + SvGlobalName name( SO3_SM_CLASSID ); + comphelper::EmbeddedObjectContainer container; + rtl::OUString aName; + uno::Reference< embed::XEmbeddedObject > ref = container.CreateEmbeddedObject( name.GetByteSequence(), aName ); + uno::Reference< uno::XInterface > component( ref->getComponent(), uno::UNO_QUERY ); + if( oox::FormulaImportBase* import = dynamic_cast< oox::FormulaImportBase* >( component.get())) + import->readFormulaOoxml( buffer ); + if (isForwardEvents()) + { + OOXMLPropertySet * pProps = new OOXMLPropertySetImpl(); + OOXMLValue::Pointer_t pVal( new OOXMLStarMathValue( ref )); + OOXMLProperty::Pointer_t pProp( new OOXMLPropertyImpl( NS_ooxml::LN_starmath, pVal, OOXMLPropertyImpl::ATTRIBUTE )); + pProps->add( pProp ); + mpStream->props( writerfilter::Reference< Properties >::Pointer_t( pProps )); + } +} }} diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx index 0d75b7d328f2..bb0e8895e808 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx @@ -641,15 +641,37 @@ private: OOXMLFastContextHandler * getFastContextHandler() const; }; +/** + A class that converts from XFastParser/XFastContextHandler usage to a liner XML stream of data. + + The purpose of this class is to convert the rather complex XFastContextHandler-based XML + processing that requires context subclasses, callbacks, etc. into a linear stream of XML tokens + that can be handled simply by reading the tokens one by one and directly processing them. + See the oox::formulaimport::XmlStream class documentation for more information. + + Usage: Create a subclass of OOXMLFastContextHandlerLinear, reimplemented getType() to provide + type of the subclass and process() to actually process the XML stream. Also make sure to + add a line like the following to model.xml (for class OOXMLFastContextHandlerMath): -class OOXMLFastContextHandlerMath: public OOXMLFastContextHandlerProperties + <resource name="CT_OMath" resource="Math"/> + + @since 3.5 +*/ +class OOXMLFastContextHandlerLinear: public OOXMLFastContextHandlerProperties { public: - explicit OOXMLFastContextHandlerMath(OOXMLFastContextHandler * pContext); - virtual string getType() const { return "Math"; } + explicit OOXMLFastContextHandlerLinear(OOXMLFastContextHandler * pContext); + /** + Return the type of the class, as written in model.xml . + */ + virtual string getType() const = 0; protected: - virtual void process(); + /** + Called when the tokens for the element, its content and sub-elements have been linearized + and should be processed. The data member @ref buffer contains the converted data. + */ + virtual void process() = 0; virtual void lcl_startFastElement(Token_t Element, const uno::Reference< xml::sax::XFastAttributeList > & Attribs) throw (uno::RuntimeException, xml::sax::SAXException); @@ -662,11 +684,21 @@ protected: virtual void lcl_characters(const ::rtl::OUString & aChars) throw (uno::RuntimeException, xml::sax::SAXException); -private: + // should be private, but not much point in making deep copies of it oox::formulaimport::XmlStreamBuilder buffer; + +private: int depthCount; }; +class OOXMLFastContextHandlerMath: public OOXMLFastContextHandlerLinear +{ +public: + explicit OOXMLFastContextHandlerMath(OOXMLFastContextHandler * pContext); + virtual string getType() const { return "Math"; } +protected: + virtual void process(); +}; }} #endif // INCLUDED_OOXML_FAST_CONTEXT_HANDLER_HXX |