Getting Started with libopc

Getting libopc

  1. Windows / Visual Studio
  2. Linux / (Debian; Ubuntu)

libopc’s Hello World

The following “Hello World” example will open the file “helloworld.docx” and dump the information to standard output.
#include <opc/opc.h>
#include <stdio.h>
int main( int argc, const char* argv[] )
{
   opcContainer *c=opcContainerOpen(_X("helloworld.docx"), 
                                    OPC_OPEN_READ_ONLY, 
                                    NULL, NULL);
   opcContainerDump(c, stdout);
   opcContainerClose(c, OPC_CLOSE_NOW);
   return 0;
}
The most recent version of the sample program can be found in sample/opc_dump.c.

To run the sample simply create an “empty” Word file and save it as “helloworld.docx”. You can also use a PowerPoint (.pptx) or an Excel (.xslx) file. The output will be similar to the following dump depending on your “helloworld.docx”:

Content Types                                                                   
--------------------------------------------------------------------------------
application/vnd.openxmlformats-officedocument.extended-properties+xml           
application/vnd.openxmlformats-officedocument.theme+xml                         
application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml    
application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml     
application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml       
application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml  
application/vnd.openxmlformats-package.core-properties+xml                      
application/vnd.openxmlformats-package.relationships+xml                        
application/xml                                                                 
--------------------------------------------------------------------------------

Extension|Type                                                    
---------|--------------------------------------------------------
rels     |application/vnd.openxmlformats-package.relationships+xml
xml      |application/xml                                         
---------|--------------------------------------------------------

Relation Types                                                                         
---------------------------------------------------------------------------------------
http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties
http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable          
http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument     
http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings           
http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles             
http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme              
http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings        
http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties  
---------------------------------------------------------------------------------------

External Relations
------------------
------------------

Part                 |Type                                                                            
---------------------|--------------------------------------------------------------------------------
docProps/app.xml     |application/vnd.openxmlformats-officedocument.extended-properties+xml           
docProps/core.xml    |application/vnd.openxmlformats-package.core-properties+xml                      
word/document.xml    |application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
word/fontTable.xml   |application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml    
word/settings.xml    |application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml     
word/styles.xml      |application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml       
word/theme/theme1.xml|application/vnd.openxmlformats-officedocument.theme+xml                         
word/webSettings.xml |application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml  
---------------------|--------------------------------------------------------------------------------

Source           |Id  |Destination          |Type                                                                                   
-----------------|----|---------------------|---------------------------------------------------------------------------------------
[root]           |rId1|word/document.xml    |http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument     
[root]           |rId2|docProps/core.xml    |http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties  
[root]           |rId3|docProps/app.xml     |http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties
word/document.xml|rId1|word/styles.xml      |http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles             
word/document.xml|rId2|word/settings.xml    |http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings           
word/document.xml|rId3|word/webSettings.xml |http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings        
word/document.xml|rId4|word/fontTable.xml   |http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable          
word/document.xml|rId5|word/theme/theme1.xml|http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme              
-----------------|----|---------------------|---------------------------------------------------------------------------------------

First you will get a list of all content types of the OPC container. The following example code will programmatically iterate through all content types:
for(xmlChar *type=opcContentTypeFirst(c);NULL!=type;type=opcContentTypeNext(c, type)) {
    printf("%s\n", type);
}
Next you will get a list of all relation types being used on the container. The following code will programmatically iterate through all relation types:
for(xmlChar *type=opcRelationTypeFirst(c);NULL!=type;type=opcRelationTypeNext(c, type)) {
    printf("%s\n", type);
}
Then all external relations targets will be listed. The following code will do this programmatically:
for(xmlChar *target=opcExternalTargetFirst(c);
    NULL!=target;
    type=opcExternalTargetNext(c, type)) {
    printf("%s\n", target);
}
Next you will get a list of all parts in the OPC package. The following code will programmatically iterate through all parts:
for(opcPart part=opcPartGetFirst(c);OPC_PART_INVALID!=part;part=opcPartGetNext(c, part)) {
   printf("%s; \n", part, opcPartGetType(c, part));
}
Finally all relations are dumped. The following code will do this programmatically:
for(opcPart part=opcPartGetFirst(c);OPC_PART_INVALID!=part;part=opcPartGetNext(c, part)) {
   for(opcRelation rel=opcRelationFirst(part, c);
       OPC_PART_INVALID!=rel;
       rel=opcRelationNext(c, rel)) {
       opcPart internal_target=opcRelationGetInternalTarget(c, part, rel);
       const xmlChar *external_target=opcRelationGetExternalTarget(c, part, rel);
       const xmlChar *target=(NULL!=internal_target?internal_target:external_target);
       const xmlChar *prefix=NULL;
       opc_uint32_t counter=-1;
       const xmlChar *type=NULL;
       opcRelationGetInformation(c, part, rel, &prefix, &counter, &type);        
       if (-1==counter) { /* no counter after prefix */
          printf("%s;%s;%s;%s\n", part, prefix, target, type);
       } else {
          printf("%s;%s%i;%s;%s\n", part, prefix, counter, target, type);
       }
   }
}
Note: A relation ID is split into a prefix part and a counter part. A counter value of (-1) means that no counter part is present. E.g. a relation id “rId1” would have a prefix value of “rId” and a counter value of “1”. The relation id “maindoc” would have a prefix value of “maindoc” and a counter value of “-1” indicating that no counter is given. If the counter value of a relation id is bigger than 2^16-1 than the counter value is set to “-1” and the entire relation id is encoded in the prefix. E.g. the relation id “rId 4294967297” would be encoded with the prefix value “rId4294967297” and the counter value of “-1”, since 4294967297 cannot be represented as a 16-bit integer. The maximum number of prefixes is 2^16.

Extracting binary streams

The following sample program will extract the part “word/document.xml” from the “helloworld.docx” container:
#include <opc/opc.h>
#include <stdio.h>
int main( int argc, const char* argv[] )
{
   opcContainer *c=opcContainerOpen(_X("helloworld.docx"), 
                                    OPC_OPEN_READ_ONLY, 
                                    NULL, NULL);
   opcPart part=opcPartFind(c, _X("word/document.xml"), NULL, 0);
   opcContainerInputStream *stream=opcContainerOpenInputStream(c, part);
   opc_uint8_t buf[100];
   opc_uint32_t len=0;
   while((len=opcContainerReadInputStream(stream, buf, sizeof(buf)))>0) {
       printf("%.*s", len, buf);
   }
   opcContainerCloseInputStream(stream);
   opcContainerClose(c, OPC_CLOSE_NOW);
   return 0;
}
The most recent version of the sample program can be found in sample/sample/opc_extract.c.

Writing binary streams

The following sample program will create the part “sample/stream.txt” in the “helloworld.docx” container:
#include <opc/opc.h>
#include <stdio.h>
#include <string.h>
int main( int argc, const char* argv[] )
{
   opcContainer *c=opcContainerOpen(_X("helloworld.docx"), 
                                    OPC_OPEN_READ_WRITE, 
                                    NULL, NULL);
   opcPart part=opcPartCreate(c, _X("word/document.xml"), _X("text/xml"), 0);
   opcContainerOutputStream *stream=opcContainerCreateOutputStream(c, part);
   const char msg[]="Hello World";
   opcContainerWriteOutputStream(stream, (const opc_uint8_t *)msg, strlen(msg));
   opcContainerCloseOutputStream(stream);
   opcContainerClose(c, OPC_CLOSE_NOW);
   return 0;
}

Last edited Jun 27, 2011 at 3:01 PM by flr, version 35

Comments

NawabMemon Mar 9, 2012 at 7:14 AM 
while writing binary stream into a document, document should not be opened.

masoodshaik Mar 2, 2012 at 9:07 AM 
Hi

Using the above code for writing binary streams in my application.Iam unable to open the document, it is getting crashed.Please tell me if there is any solution to solve this.