summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2011-12-02 17:38:51 +0100
committerLuboš Luňák <l.lunak@suse.cz>2011-12-07 14:47:11 +0100
commit7be8bac42aa578dc7f250a490634e13d1dac550b (patch)
treec9b51c1b92a6683d50277038549243cd59eed7d5
parent1e4fb45c03e1787a6f73a93a1d9a68911d17a4e6 (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.hxx62
-rw-r--r--oox/source/mathml/importutils.cxx2
-rw-r--r--starmath/source/ooxmlimport.cxx4
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx58
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.hxx42
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