[Libreoffice-commits] core.git: sw/qa sw/source writerfilter/inc writerfilter/source

sushil_shinde sushil.shinde at synerzip.com
Tue Nov 5 16:07:28 CET 2013


 sw/qa/extras/ooxmlexport/data/customxml.docx    |binary
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx        |   28 ++++++++++++
 sw/source/filter/ww8/docxexport.cxx             |   43 +++++++++++++++++++
 sw/source/filter/ww8/docxexport.hxx             |    1 
 writerfilter/inc/ooxml/OOXMLDocument.hxx        |    3 -
 writerfilter/source/filter/ImportFilter.cxx     |   32 ++++++++++++++
 writerfilter/source/ooxml/OOXMLDocumentImpl.cxx |   54 ++++++++++++++++++++++++
 writerfilter/source/ooxml/OOXMLDocumentImpl.hxx |    5 +-
 writerfilter/source/ooxml/OOXMLStreamImpl.cxx   |   20 ++++++++
 writerfilter/source/ooxml/OOXMLStreamImpl.hxx   |    3 +
 10 files changed, 184 insertions(+), 5 deletions(-)

New commits:
commit 8ab553117e038ec1eab76ac1c3d8a0b5aa968baa
Author: sushil_shinde <sushil.shinde at synerzip.com>
Date:   Fri Nov 1 19:21:01 2013 +0530

    [docx] CustomXml saved in InteropGrabBag and exported customxml when saving.
    
      The XDocuments representing the DOM of an OOXML's customxml document is
      stored as the PropertyValue "OOXCustomXml" into the "InteropGraBag".
    
      Added mxCustomXmlDomList object which holds xDocuments for
      each item.xml from CustomXml.
    
      Exporting all items dom tree from customxml that has been parsed
      when loading the file.
      This is necessary in order to properly reopen docx files that
      contain data like citation.
    
      This fix grab bags only item[n].xml's files from CustomXml folder.
      itemProps[n].xml's and item.xml's .rels are not preserved and exported yet.
      (Working on this part)
    
    Change-Id: I330f34f38a7aa4cd39094371bff15ebbc0318167
    Reviewed-on: https://gerrit.libreoffice.org/6519
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/extras/ooxmlexport/data/customxml.docx b/sw/qa/extras/ooxmlexport/data/customxml.docx
new file mode 100644
index 0000000..bfdf8ec
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/customxml.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index f8b7904..028189b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -1506,6 +1506,34 @@ DECLARE_OOXML_TEST(testCharHighlight, "char_highlight.docx")
     }
 }
 
+DECLARE_OOXML_TEST(testCustomXmlGrabBag, "customxml.docx")
+{
+   // The problem was that CustomXml/item[n].xml files were missing from docx file after saving file.
+   // This test case tests whether customxml files grabbagged properly in correct object.
+
+   uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+   uno::Reference<beans::XPropertySet> xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY);
+   uno::Sequence<beans::PropertyValue> aGrabBag(0);
+   xTextDocumentPropertySet->getPropertyValue(OUString("InteropGrabBag")) >>= aGrabBag;
+   CPPUNIT_ASSERT(aGrabBag.hasElements()); // Grab Bag not empty
+   sal_Bool CustomXml = sal_False;
+   for(int i = 0; i < aGrabBag.getLength(); ++i)
+   {
+       if (aGrabBag[i].Name == OUString("OOXCustomXml"))
+       {
+           CustomXml = sal_True;
+           uno::Reference<xml::dom::XDocument> aCustomXmlDom;
+           uno::Sequence<uno::Reference<xml::dom::XDocument> > aCustomXmlDomList;
+           CPPUNIT_ASSERT(aGrabBag[i].Value >>= aCustomXmlDomList); // PropertyValue of proper type
+           sal_Int32 length = aCustomXmlDomList.getLength();
+           CPPUNIT_ASSERT_EQUAL(sal_Int32(3), length);
+           aCustomXmlDom = aCustomXmlDomList[1];
+           CPPUNIT_ASSERT(aCustomXmlDom.get()); // Reference not empty
+       }
+   }
+   CPPUNIT_ASSERT(CustomXml); // Grab Bag has all the expected elements
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 69fc7e9..40112cf 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -351,6 +351,8 @@ void DocxExport::ExportDocument_Impl()
 
     WriteTheme();
 
+    WriteCustomXml();
+
     delete pStyles, pStyles = NULL;
     delete m_pSections, m_pSections = NULL;
 }
@@ -782,6 +784,47 @@ void DocxExport::WriteTheme()
         uno::Sequence< beans::StringPair >() );
 }
 
+void DocxExport::WriteCustomXml()
+{
+    uno::Reference< beans::XPropertySet > xPropSet( pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
+
+    uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+    OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
+    if ( !xPropSetInfo->hasPropertyByName( pName ) )
+        return;
+
+    uno::Sequence<uno::Reference<xml::dom::XDocument> > customXmlDomlist;
+    uno::Sequence< beans::PropertyValue > propList;
+    xPropSet->getPropertyValue( pName ) >>= propList;
+    for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp )
+    {
+        OUString propName = propList[nProp].Name;
+        if ( propName == "OOXCustomXml" )
+        {
+             propList[nProp].Value >>= customXmlDomlist;
+             break;
+        }
+    }
+
+    for (sal_Int32 j = 1; j < customXmlDomlist.getLength(); j++) {
+
+        uno::Reference<xml::dom::XDocument> customXmlDom = customXmlDomlist[j];
+        if ( customXmlDom.is() )
+        {
+            m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
+                    "../customXml/item"+OUString::number(j)+".xml" );
+
+            uno::Reference< xml::sax::XSAXSerializable > serializer( customXmlDom, uno::UNO_QUERY );
+            uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() );
+            writer->setOutputStream( GetFilter().openFragmentStream( "customXml/item"+OUString::number(j)+".xml",
+                "application/xml" ) );
+            serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
+                uno::Sequence< beans::StringPair >() );
+        }
+    }
+}
+
 VMLExport& DocxExport::VMLExporter()
 {
     return *m_pVMLExport;
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 18017d1..531dcc5 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -207,6 +207,7 @@ private:
     /// Write word/theme/theme1.xml
     void WriteTheme();
 
+    void WriteCustomXml();
     /// All xml namespaces to be used at the top of any text .xml file (main doc, headers, footers,...)
     sax_fastparser::XFastAttributeListRef MainXmlNamespaces( sax_fastparser::FSHelperPtr serializer );
 
diff --git a/writerfilter/inc/ooxml/OOXMLDocument.hxx b/writerfilter/inc/ooxml/OOXMLDocument.hxx
index 1f4930b..2fb68a5 100644
--- a/writerfilter/inc/ooxml/OOXMLDocument.hxx
+++ b/writerfilter/inc/ooxml/OOXMLDocument.hxx
@@ -76,7 +76,7 @@ class WRITERFILTER_OOXML_DLLPUBLIC OOXMLStream
 {
 public:
     enum StreamType_t { UNKNOWN, DOCUMENT, STYLES, FONTTABLE, NUMBERING,
-        FOOTNOTES, ENDNOTES, COMMENTS, THEME, SETTINGS, VBAPROJECT };
+        FOOTNOTES, ENDNOTES, COMMENTS, THEME, CUSTOMXML, SETTINGS, VBAPROJECT };
     typedef boost::shared_ptr<OOXMLStream> Pointer_t;
 
     virtual ~OOXMLStream() {}
@@ -242,6 +242,7 @@ public:
     virtual void setShapeContext( uno::Reference<xml::sax::XFastShapeContextHandler> xContext ) = 0;
     virtual uno::Reference<xml::dom::XDocument> getThemeDom( ) = 0;
     virtual void setThemeDom( uno::Reference<xml::dom::XDocument> xThemeDom ) = 0;
+    virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getCustomXmlDomList( ) = 0;
 };
 
 
diff --git a/writerfilter/source/filter/ImportFilter.cxx b/writerfilter/source/filter/ImportFilter.cxx
index 94a98a9..2cbf834 100644
--- a/writerfilter/source/filter/ImportFilter.cxx
+++ b/writerfilter/source/filter/ImportFilter.cxx
@@ -148,6 +148,38 @@ sal_Bool WriterFilter::filter( const uno::Sequence< beans::PropertyValue >& aDes
         }
         catch(const uno::Exception&)
         {
+            SAL_WARN("writerfilter","Failed to save theme dom to documents grab bag");
+        }
+
+        // Adding the saved custom xml DOM to the document's grab bag
+        try
+        {
+              uno::Reference<beans::XPropertySet> xDocProps(m_xDstDoc, uno::UNO_QUERY);
+              if (xDocProps.is())
+              {
+                  uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
+
+                  const OUString& aGrabBagPropName = OUString("InteropGrabBag");
+                  if( xPropsInfo.is() && xPropsInfo->hasPropertyByName( aGrabBagPropName ) )
+                  {
+                      uno::Sequence<beans::PropertyValue> aGrabBag;
+
+                      // We want to keep the previous items
+                      xDocProps->getPropertyValue( aGrabBagPropName ) >>= aGrabBag;
+                      sal_Int32 length = aGrabBag.getLength();
+                      aGrabBag.realloc(length+1);
+
+                      beans::PropertyValue* pValue = aGrabBag.getArray();
+                      pValue[length].Name = "OOXCustomXml";
+                      pValue[length].Value = uno::makeAny( pDocument->getCustomXmlDomList() );
+
+                      xDocProps->setPropertyValue( aGrabBagPropName, uno::Any( aGrabBag ) );
+                  }
+              }
+        }
+        catch(const uno::Exception&)
+        {
+            SAL_WARN("writerfilter","Failed to save custom xml dom to documents grab bag");
         }
 
         writerfilter::ooxml::OOXMLStream::Pointer_t  pVBAProjectStream(writerfilter::ooxml::OOXMLDocumentFactory::createStream( pDocStream, writerfilter::ooxml::OOXMLStream::VBAPROJECT ));
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
index c77cebb..f3ba179 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
@@ -21,8 +21,10 @@
 
 #include <com/sun/star/xml/sax/SAXException.hpp>
 #include <com/sun/star/xml/dom/DocumentBuilder.hpp>
+#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
 #include <doctok/resourceids.hxx>
 #include <ooxml/resourceids.hxx>
+#include "OOXMLStreamImpl.hxx"
 #include "OOXMLDocumentImpl.hxx"
 #include "OOXMLBinaryObjectReference.hxx"
 #include "OOXMLFastDocumentHandler.hxx"
@@ -31,6 +33,8 @@
 
 #include <iostream>
 
+// this extern variable is declared in OOXMLStreamImpl.hxx
+OUString customTarget;
 using ::com::sun::star::xml::sax::SAXException;
 namespace writerfilter {
 namespace ooxml
@@ -374,6 +378,9 @@ void OOXMLDocumentImpl::resolve(Stream & rStream)
         resolveFastSubStream(rStream, OOXMLStream::SETTINGS);
         mxThemeDom = importSubStream(OOXMLStream::THEME);
         resolveFastSubStream(rStream, OOXMLStream::THEME);
+        // Custom xml's are handled as part of grab bag.
+        resolveCustomXmlStream(rStream);
+
         resolveFastSubStream(rStream, OOXMLStream::FONTTABLE);
         resolveFastSubStream(rStream, OOXMLStream::STYLES);
         resolveFastSubStream(rStream, OOXMLStream::NUMBERING);
@@ -399,6 +406,48 @@ void OOXMLDocumentImpl::resolve(Stream & rStream)
 #endif
 }
 
+void OOXMLDocumentImpl::resolveCustomXmlStream(Stream & rStream){
+    // Resolving all item[n].xml files from CustomXml folder.
+    uno::Reference<embed::XRelationshipAccess> mxRelationshipAccess;
+    mxRelationshipAccess.set((*dynamic_cast<OOXMLStreamImpl *>(mpStream.get())).accessDocumentStream(), uno::UNO_QUERY_THROW);
+    if (mxRelationshipAccess.is())
+    {
+        OUString sCustomType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml");
+        OUString sTarget("Target");
+        bool bFound = false;
+        sal_Int32 counter = 1;
+        uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs =
+                mxRelationshipAccess->getAllRelationships();
+        uno::Sequence<uno::Reference<xml::dom::XDocument> > mxCustomXmlDomListTemp(aSeqs.getLength());
+        for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
+        {
+            uno::Sequence< beans::StringPair > aSeq = aSeqs[j];
+            for (sal_Int32 i = 0; i < aSeq.getLength(); i++)
+            {
+                beans::StringPair aPair = aSeq[i];
+                // Need to resolve only customxml files from document relationships.
+                // Skipping other files.
+                if (aPair.Second.compareTo(sCustomType) == 0)
+                    bFound = true;
+                else if(aPair.First.compareTo(sTarget) == 0 && bFound){
+                    // Adding value to extern variable customTarget. It will be used in ooxmlstreamimpl
+                    // to ensure customxml target is visited in lcl_getTarget.
+                    customTarget = aPair.Second;
+                }
+            }
+            if(bFound){
+                uno::Reference<xml::dom::XDocument> temp = importSubStream(OOXMLStream::CUSTOMXML);
+                mxCustomXmlDomListTemp[counter] = temp;
+                counter++;
+                resolveFastSubStream(rStream, OOXMLStream::CUSTOMXML);
+                bFound = false;
+            }
+        }
+        mxCustomXmlDomListTemp.realloc(counter+1);
+        mxCustomXmlDomList = mxCustomXmlDomListTemp;
+    }
+}
+
 uno::Reference<io::XInputStream> OOXMLDocumentImpl::getInputStreamForId(const OUString & rId)
 {
     OOXMLStream::Pointer_t pStream(OOXMLDocumentFactory::createStream(mpStream, rId));
@@ -461,6 +510,11 @@ uno::Reference<xml::dom::XDocument> OOXMLDocumentImpl::getThemeDom( )
     return mxThemeDom;
 }
 
+uno::Sequence<uno::Reference<xml::dom::XDocument> > OOXMLDocumentImpl::getCustomXmlDomList( )
+{
+    return mxCustomXmlDomList;
+}
+
 OOXMLDocument *
 OOXMLDocumentFactory::createDocument
 (OOXMLStream::Pointer_t pStream)
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
index bf18504..2ec5033 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
@@ -42,7 +42,7 @@ class OOXMLDocumentImpl : public OOXMLDocument
     uno::Reference<drawing::XDrawPage> mxDrawPage;
     uno::Reference<xml::sax::XFastShapeContextHandler> mxShapeContext;
     uno::Reference<xml::dom::XDocument> mxThemeDom;
-
+    uno::Sequence<uno::Reference<xml::dom::XDocument> > mxCustomXmlDomList;
     bool mbIsSubstream;
 
 protected:
@@ -64,6 +64,7 @@ protected:
                    const sal_Int32 nNoteId);
 
     void setIsSubstream( bool bSubstream ) { mbIsSubstream = bSubstream; };
+    void resolveCustomXmlStream(Stream & rStream);
 
 public:
     OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream);
@@ -110,7 +111,7 @@ public:
     virtual void setShapeContext( uno::Reference<xml::sax::XFastShapeContextHandler> xContext );
     virtual void setThemeDom(uno::Reference<xml::dom::XDocument> xThemeDom);
     virtual uno::Reference<xml::dom::XDocument> getThemeDom();
-
+    virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getCustomXmlDomList();
 };
 }}
 #endif // OOXML_DOCUMENT_IMPL_HXX
diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
index 96f37bd..293b695 100644
--- a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
@@ -110,6 +110,7 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
     static OUString sEndnotesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes");
     static OUString sCommentsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments");
     static OUString sThemeType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme");
+    static OUString sCustomType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml");
     static OUString sSettingsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings");
     static OUString sTarget("Target");
     static OUString sTargetMode("TargetMode");
@@ -147,6 +148,9 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
         case THEME:
             sStreamType = sThemeType;
             break;
+        case CUSTOMXML:
+            sStreamType = sCustomType;
+            break;
         case SETTINGS:
             sStreamType = sSettingsType;
             break;
@@ -175,8 +179,15 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
                 else if (aPair.First.compareTo(sId) == 0 &&
                          aPair.Second.compareTo(rId) == 0)
                     bFound = true;
-                else if (aPair.First.compareTo(sTarget) == 0)
-                    sMyTarget = aPair.Second;
+                else if (aPair.First.compareTo(sTarget) == 0){
+                    // checking item[n].xml is not visited already.
+                    if(customTarget != aPair.Second && sStreamType == sCustomType){
+                        bFound = false;
+                    }
+                    else {
+                        sMyTarget = aPair.Second;
+                    }
+                }
                 else if (aPair.First.compareTo(sTargetMode) == 0 &&
                          aPair.Second.compareTo(sExternal) == 0)
                     bExternalTarget = true;
@@ -260,6 +271,11 @@ uno::Reference<io::XInputStream> OOXMLStreamImpl::getDocumentStream()
     return xResult;
 }
 
+// Giving access to mxDocumentStream. It is needed by resolving custom xml to get list of customxml's used in document.
+uno::Reference<io::XStream> OOXMLStreamImpl::accessDocumentStream(){
+    return mxDocumentStream;
+}
+
 uno::Reference<io::XInputStream> OOXMLStreamImpl::getStorageStream()
 {
     return mxStorageStream;
diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.hxx b/writerfilter/source/ooxml/OOXMLStreamImpl.hxx
index 80065f6..8c0c21b 100644
--- a/writerfilter/source/ooxml/OOXMLStreamImpl.hxx
+++ b/writerfilter/source/ooxml/OOXMLStreamImpl.hxx
@@ -24,6 +24,8 @@
 #include <com/sun/star/embed/XRelationshipAccess.hpp>
 #include <com/sun/star/io/XStream.hpp>
 
+extern OUString customTarget;
+
 namespace writerfilter {
 namespace ooxml
 {
@@ -78,6 +80,7 @@ public:
     getFastTokenHandler(uno::Reference<uno::XComponentContext> rContext);
 
     void setInputStream(uno::Reference<io::XInputStream> rxInputStream);
+    uno::Reference<io::XStream> accessDocumentStream();
 };
 }}
 #endif // INCLUDED_OOXML_STREAM_IMPL_HXX


More information about the Libreoffice-commits mailing list