Hi attached is a patch which generates and uses hn.class selectors.
Generated from the filter/odf/ directory via git diff On Tue, Jun 2, 2015 at 12:43 AM, Peter Kelly <pmke...@apache.org> wrote: > (apologies if this is a duplicate - I sent from the wrong email address > before) > > > On 31 May 2015, at 7:09 pm, Ian C <i...@amham.net <mailto:i...@amham.net>> > wrote: > > > > We also need to take into account the style hierarchy. I see from some > of the CSS documentation that there are mechanisms in place to manage that > but have not looked in detail. Any advice Peter? > > First, some general comments - what I recommend is to first build up a > custom data structure representing all the styles which can later be > queried when needed, e.g. when you encounter an element in content.xml that > has a particular style associated with it. > > In the Word filter, there are two classes used for this purpose: WordSheet > and WordStyle (the former being a collection of the latter). These are > defined in WordSheet.h and WordSheet.c. Early in the conversion process, > the filter goes through the XML document containing the styles and builds > up this data structure. This results in the code being able to deal with > the styles at a higher-level of abstraction than examining the DOM tree of > styles.xml directly. > > A while ago I made a start on the same thing for ODF - there’s ODFSheet > and ODFStyle classes defined for the same purpose. So a good next step for > tackling styles would be to traverse the DOM tree of styles.xml and > populate this data structure, creating a new ODFStyle object for each style > in the document, and adding them to the (single) ODFSheet object for the > document. This data structure could then be used to generate the CSS text, > as is done in the Word filter. > > > I just generated to div tags do we want that? Mapping to h1... hn could > be a better way but not sure how to really map the correct heading styles > to the hn. > > In the case of ODF, the information about what header to map to is > (usually) available more directly than in OOXML. Both specs refer to it as > the “outline level”. In an ODF document, heading outline levels start from > 1 (just like HTML), but you also have the distinction between <text:h> and > <text:p> elements, so you can know whether something is a heading or a > regular paragraph. > > When encountering a <text:h> element, you can determine the outline level > from the attribute, e.g.: > > <text:h text:style-name="Heading_20_1" text:outline-level="1">Headline > One</text:h> > > So here the value ‘1’ is sufficient information to indicate that you need > to create a h1 element. The style-name attribute is Heading_20_1, so the > corresponding CSS would need to be: > > h1.Heading_20_1 { > } > > and similarly for other levels, e.g. > > h2.Heading_20_2 { > } > > Note that, as with your existing code, this would be generated separately > from the content itself, solely based on the information in styles.xml, for > the non-automatic styles. > > So I suggest separating buildCSS_Styles into two separate functions: One > which populates the CSSSheet object associated with the package (that is, > package->sheet, which I think is already created), and another which > examines the ODFSheet object and populates the CSSSheet object. > > — > Dr Peter M. Kelly > pmke...@apache.org > > PGP key: http://www.kellypmk.net/pgp-key <http://www.kellypmk.net/pgp-key> > (fingerprint 5435 6718 59F0 DD1F BFA0 5E46 2523 BAA1 44AE 2966) > > -- Cheers, Ian C
diff --git a/DocFormats/filters/odf/src/text/ODFText.c b/DocFormats/filters/odf/src/text/ODFText.c index 4ef0068..7e3e3dc 100644 --- a/DocFormats/filters/odf/src/text/ODFText.c +++ b/DocFormats/filters/odf/src/text/ODFText.c @@ -21,6 +21,9 @@ #include "ODFPackage.h" #include "ODFTextConverter.h" #include "DFDOM.h" +#include "DFHTML.h" +#include "DFHTMLNormalization.h" +#include "CSS.h" #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -42,7 +45,7 @@ static void traverseContent(ODFTextConverter *conv, DFNode *odfNode, DFNode *htm if (odfChild->tag == DOM_TEXT) { // we have some text or a text modfier here. // DFNode *check = - DFCreateChildTextNode(htmlNode, odfChild->value); +// DFCreateChildTextNode(htmlNode, odfChild->value); printf(YELLOW "DOM_TEXT: %s \n" RESET, odfChild->value ); @@ -70,8 +73,33 @@ static void traverseContent(ODFTextConverter *conv, DFNode *odfNode, DFNode *htm // DFNode *newChild = DFCreateChildElement(htmlNode, newTag); } else { - DFCreateChildElement(htmlNode, newTag); - } + //what do we have here + + DFNode *node = NULL; + const char * styleName = DFGetAttribute(odfChild,TEXT_STYLE_NAME); + const char * outlevel = DFGetAttribute(odfChild,TEXT_OUTLINE_LEVEL); + if(outlevel != NULL) { + int s_val = atoi(&outlevel[strlen(outlevel)-1]) - 1; + //if (s_val >= 0 && s_val < 6) { + // HTML_H1 + s_val; + //} + node = DFCreateChildElement(htmlNode, HTML_H1 + s_val); + } else { + node = DFCreateChildElement(htmlNode, HTML_P); + } + printf("Found style name %s\n", styleName); + DFSetAttribute(node, HTML_CLASS, styleName); //DFGetAttribute(odfNode,TEXT_STYLE_NAME)); + for (DFNode *domChild = odfChild->first; domChild != NULL; domChild = domChild->next) + { + if (domChild->tag == DOM_TEXT) { // we have some text or a text modfier here. + // DFNode *check = + DFCreateChildTextNode(node, domChild->value); + printf(YELLOW "DOM_TEXT: %s \n" RESET, + domChild->value + ); + } + } + } } traverseContent(conv,odfChild,htmlNode); } @@ -95,26 +123,53 @@ DFDocument *ODFTextGet(DFStorage *concreteStorage, DFStorage *abstractStorage, c html = DFDocumentNewWithRoot(HTML_HTML); body = DFCreateChildElement(html->root, HTML_BODY); + DFNode *head = DFChildWithTag(html->root,HTML_HEAD); + if (head == NULL) { + head = DFCreateElement(html,HTML_HEAD); + DFNode *body = DFChildWithTag(html->root,HTML_BODY); + DFInsertBefore(html->root,head,body); + } conv = ODFTextConverterNew(html, abstractStorage, package, idPrefix); - printf(YELLOW + printf(RED "============================================================\n" - "Showing ODF nodes prior to the traverseContent function\n" + "Process ODF style nodes prior to the traverseContent function\n" "============================================================\n" RESET); - show_nodes(package->contentDoc->root); + printf(GREEN "Number of style nodes: %lu\n" RESET, (unsigned long)package->stylesDoc->nodesCount); + show_nodes(package->stylesDoc->root, 0); + //we want to build up the CSS Stylesheet + CSSSheet * cssSheet = CSSSheetNew(); + buildCSS_Styles(cssSheet, package->stylesDoc->root); + + printf(GREEN "CSS: %s\n" RESET, CSSSheetCopyCSSText(cssSheet)); + print_line(2); print_line(2); print_line(2); + printf(YELLOW + "============================================================\n" + "Showing ODF content nodes prior to the traverseContent function\n" + "============================================================\n" + RESET); + + show_nodes(package->contentDoc->root, 0); + print_line(2); + print_line(2); + print_line(2); + + // TODO: Traverse the DOM tree of package->contentDoc, adding elements to the HTML document. // contentDoc is loaded from content.xml, and represents the most important information in // the document, i.e. the text, tables, lists, etc. traverseContent(conv, package->contentDoc->root, body); - + char *cssText = CSSSheetCopyCSSText(cssSheet); + HTMLAddInternalStyleSheet(conv->html, cssText); + HTML_safeIndent(conv->html->docNode,0); // uncomment to see the result. (spammy!) printf(GREEN "============================================================\n" @@ -122,7 +177,7 @@ DFDocument *ODFTextGet(DFStorage *concreteStorage, DFStorage *abstractStorage, c "============================================================\n" RESET); - show_nodes(body); + show_nodes(body, 0); // TODO: Once this basic traversal is implemented and is capable of producing paragraphs, diff --git a/DocFormats/filters/odf/src/text/gbg_test.c b/DocFormats/filters/odf/src/text/gbg_test.c index fae6c42..79afde8 100644 --- a/DocFormats/filters/odf/src/text/gbg_test.c +++ b/DocFormats/filters/odf/src/text/gbg_test.c @@ -3,6 +3,9 @@ #include "ODFPackage.h" #include "ODFTextConverter.h" #include "DFDOM.h" + +#include "CSS.h" +#include "CSSSheet.h" #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -189,11 +192,144 @@ Tag find_HTML(DFNode *odfNode, DFNode *htmlNode) /** * Dev tool: List all the nodes following the given one. */ -void show_nodes(DFNode *odfNode) +void show_nodes(DFNode *odfNode, int level) +{ + printf("Level: %d\n",level); + level++; + print_node_info(odfNode); + for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) { + walkChildren(odfChild, level); + } +} + +/** + * Dev tool: List all the nodes following the given one. + */ +void walkChildren(DFNode *odfNode, int level) { + printf("Level: %d\n",level); + level++; + print_node_info(odfNode); for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) { - print_node_info(odfChild); - print_line(0); + walkChildren(odfChild, level); + } +} + +/** + * Dev tool: List all the nodes below the given one. + */ +/*void show_nodes(DFNode *odfNode, int level) +{ + DFNode *nextNode = odfNode; + do { + print_node_info(nextNode); + nextNode = DFNextNode(nextNode); + }while(nextNode != NULL); +}*/ + +//give me the styles document +void buildCSS_Styles(CSSSheet * cssSheet, DFNode *odfNode) +{ + //walk through the nodes + // go to the office:styles can we find it? + //iterate each style:style + // make a css + // dip down to get its attributes + printf("buildCSS_Styles\n"); + printf("name = %s\n", translateXMLEnumName[odfNode->tag]); + + //manually play with the functions first + + +/* CSSStyle* cssStyle = CSSSheetLookupElement(cssSheet, + "elementName", + "className", + 1, + 0); + CSSProperties * localproperties = CSSStyleRule(cssStyle); + CSSPut(localproperties,"font-weight","bold");*/ + + + + for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) + { + if(odfChild->tag == OFFICE_STYLES) + { + printf("Processing office styles\n"); + for (DFNode *styleNode = odfChild->first; styleNode != NULL; styleNode = styleNode->next) + { + if(styleNode->tag == STYLE_STYLE) + { + for (unsigned int i = 0; i < styleNode->attrsCount; i++) + { + Tag t = styleNode->attrs[i].tag; + if(t == STYLE_NAME) + { + printf("Create CSS Properties for %s\n", styleNode->attrs[i].value); + + //if this is a heading look for the TEXT_OUTLINE_LEVEL + + // use the attrbute fetch thing... + const char* outlevel = DFGetAttribute(styleNode, STYLE_DEFAULT_OUTLINE_LEVEL); + CSSStyle* cssStyle = NULL; + if(outlevel != NULL) { + char hlevel[4] = "h"; + hlevel[1] = outlevel[0]; + hlevel[2] = 0; + + cssStyle = CSSSheetLookupElement(cssSheet, + hlevel, + styleNode->attrs[i].value, + 1, + 0); + } else { + cssStyle = CSSSheetLookupElement(cssSheet, + "div", + styleNode->attrs[i].value, + 1, + 0); + } + for (DFNode *styleInfo = styleNode->first; styleInfo != NULL; styleInfo = styleInfo->next) + { + if(styleInfo->tag == STYLE_TEXT_PROPERTIES) + { + //just looking for bolds as a first cut + for (unsigned int i = 0; i < styleInfo->attrsCount; i++) + { + Tag t = styleInfo->attrs[i].tag; + switch(t) + { + case FO_FONT_WEIGHT: + { + CSSProperties * localproperties = CSSStyleRule(cssStyle); + CSSPut(localproperties,"font-weight",styleInfo->attrs[i].value); + break; + } + case FO_FONT_SIZE: + { + CSSProperties * localproperties = CSSStyleRule(cssStyle); + CSSPut(localproperties,"font-size",styleInfo->attrs[i].value); + break; + } + case STYLE_FONT_NAME: + { + CSSProperties * localproperties = CSSStyleRule(cssStyle); + CSSPut(localproperties,"font-family",styleInfo->attrs[i].value); + break; + } + } + } + } + else if(styleInfo->tag == STYLE_PARAGRAPH_PROPERTIES) + { + //TBD + } + } + } + } + } + } + } } } diff --git a/DocFormats/filters/odf/src/text/gbg_test.h b/DocFormats/filters/odf/src/text/gbg_test.h index 636165f..3645c8e 100644 --- a/DocFormats/filters/odf/src/text/gbg_test.h +++ b/DocFormats/filters/odf/src/text/gbg_test.h @@ -3,10 +3,14 @@ #define TAG_NOT_FOUND 4040404 #define TAG_NOT_MATCHED 777777 +#include "CSS.h" +#include "CSSSheet.h" Tag find_HTML(DFNode *odfNode, DFNode *htmlNode); void print_node_info(DFNode *node); -void show_nodes(DFNode *node); +void show_nodes(DFNode *node, int level); +void walkChildren(DFNode *odfNode, int level); +void buildCSS_Styles(CSSSheet * cssSheet, DFNode *odfNode); char *node_id_info(DFNode *node); char *missing_tag_info(DFNode *node); void print_line(int style);
// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include "DFPlatform.h" #include "ODFText.h" #include "ODFPackage.h" #include "ODFTextConverter.h" #include "DFDOM.h" #include "DFHTML.h" #include "DFHTMLNormalization.h" #include "CSS.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include "DFXMLNames.h" #include "gbg_test.h" #include "color.h" typedef struct { ODFTextConverter *conv; DFDocument *contentDoc; DFHashTable *numIdByHtmlId; DFHashTable *htmlIdByNumId; } ODFPutData; // I'm not sure what ODFTextConverter ise used here for. static void traverseContent(ODFTextConverter *conv, DFNode *odfNode, DFNode *htmlNode) { for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) { if (odfChild->tag == DOM_TEXT) { // we have some text or a text modfier here. // DFNode *check = // DFCreateChildTextNode(htmlNode, odfChild->value); printf(YELLOW "DOM_TEXT: %s \n" RESET, odfChild->value ); // print_node_info(check); // print_line(1); } else { Tag newTag = find_HTML(odfChild, htmlNode); if (newTag == TAG_NOT_FOUND) { // We found a new tag that we need to add to // find_HTML(), which reports this to stdout // currently. ; } else if (newTag == TAG_NOT_MATCHED) { // we find tag that we have not managed to match, but // that is in find_HTML() already. DFCreateChildTextNode(htmlNode, missing_tag_info(odfChild)); ; } else if (!newTag) { ; // we added an attribute node already in find_HTML (for now) // DFNode *newChild = DFCreateChildElement(htmlNode, newTag); } else { //what do we have here DFNode *node = NULL; const char * styleName = DFGetAttribute(odfChild,TEXT_STYLE_NAME); const char * outlevel = DFGetAttribute(odfChild,TEXT_OUTLINE_LEVEL); if(outlevel != NULL) { int s_val = atoi(&outlevel[strlen(outlevel)-1]) - 1; //if (s_val >= 0 && s_val < 6) { // HTML_H1 + s_val; //} node = DFCreateChildElement(htmlNode, HTML_H1 + s_val); } else { node = DFCreateChildElement(htmlNode, HTML_P); } printf("Found style name %s\n", styleName); DFSetAttribute(node, HTML_CLASS, styleName); //DFGetAttribute(odfNode,TEXT_STYLE_NAME)); for (DFNode *domChild = odfChild->first; domChild != NULL; domChild = domChild->next) { if (domChild->tag == DOM_TEXT) { // we have some text or a text modfier here. // DFNode *check = DFCreateChildTextNode(node, domChild->value); printf(YELLOW "DOM_TEXT: %s \n" RESET, domChild->value ); } } } } traverseContent(conv,odfChild,htmlNode); } // TODO: Add a switch statement here to check the type of ODF element, and use // DFCreateChildElement to create a new element in the HTML document as a child of htmlNode // based on the type. As this function gets more complicated, it will likely be useful to // split it up into several functions } DFDocument *ODFTextGet(DFStorage *concreteStorage, DFStorage *abstractStorage, const char *idPrefix, DFError **error) { int ok = 0; DFDocument *html = NULL; ODFPackage *package = NULL; ODFTextConverter *conv = NULL; DFNode *body = NULL; package = ODFPackageOpenFrom(concreteStorage, error); if (package == NULL) goto end; html = DFDocumentNewWithRoot(HTML_HTML); body = DFCreateChildElement(html->root, HTML_BODY); DFNode *head = DFChildWithTag(html->root,HTML_HEAD); if (head == NULL) { head = DFCreateElement(html,HTML_HEAD); DFNode *body = DFChildWithTag(html->root,HTML_BODY); DFInsertBefore(html->root,head,body); } conv = ODFTextConverterNew(html, abstractStorage, package, idPrefix); printf(RED "============================================================\n" "Process ODF style nodes prior to the traverseContent function\n" "============================================================\n" RESET); printf(GREEN "Number of style nodes: %lu\n" RESET, (unsigned long)package->stylesDoc->nodesCount); show_nodes(package->stylesDoc->root, 0); //we want to build up the CSS Stylesheet CSSSheet * cssSheet = CSSSheetNew(); buildCSS_Styles(cssSheet, package->stylesDoc->root); printf(GREEN "CSS: %s\n" RESET, CSSSheetCopyCSSText(cssSheet)); print_line(2); print_line(2); print_line(2); printf(YELLOW "============================================================\n" "Showing ODF content nodes prior to the traverseContent function\n" "============================================================\n" RESET); show_nodes(package->contentDoc->root, 0); print_line(2); print_line(2); print_line(2); // TODO: Traverse the DOM tree of package->contentDoc, adding elements to the HTML document. // contentDoc is loaded from content.xml, and represents the most important information in // the document, i.e. the text, tables, lists, etc. traverseContent(conv, package->contentDoc->root, body); char *cssText = CSSSheetCopyCSSText(cssSheet); HTMLAddInternalStyleSheet(conv->html, cssText); HTML_safeIndent(conv->html->docNode,0); // uncomment to see the result. (spammy!) printf(GREEN "============================================================\n" "Showing HTML nodes after the traverseContent function\n" "============================================================\n" RESET); show_nodes(body, 0); // TODO: Once this basic traversal is implemented and is capable of producing paragraphs, // tables, lists, and spans, add ids to the HTML elements as they are created. That is, set // the id attribute of each new HTML element to a string containing the idPrefix followed by // the seqNo field of the node in contentDoc from which the HTML element was generated. // // These id attributes can then later be used in ODFTextPut to figure out which elements in an // updated HTML file correspond to existing elements in the ODF content document, which lets us // retain information in the ODF file that could not be translated to HTML during the get. // // See WordConverterCreateAbstract and WordConverterGetConcrete for how this is done in the // Word filter. ok = 1; end: ODFPackageRelease(package); ODFTextConverterRelease(conv); if (!ok) { DFDocumentRelease(html); return NULL; } return html; } int ODFTextPut(DFStorage *concreteStorage, DFStorage *abstractStorage, DFDocument *htmlDoc, const char *idPrefix, DFError **error) { DFErrorFormat(error,"ODFTextPut: Not yet implemented"); return 0; } int ODFTextCreate(DFStorage *concreteStorage, DFStorage *abstractStorage, DFDocument *htmlDoc, DFError **error) { DFErrorFormat(error,"ODFTextCreate: Not yet implemented"); return 0; }
#include "DFPlatform.h" #include "ODFText.h" #include "ODFPackage.h" #include "ODFTextConverter.h" #include "DFDOM.h" #include "CSS.h" #include "CSSSheet.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include "DFXMLNames.h" #include "DFNameMap.h" #include "color.h" #include "gbg_test.h" /* G: Advice I have still to cover: ================================ printNode: The attrs field of the DFNode struct is an array, not a single object. It contains attrsCount elements. Accessing it in the way that printNode does is incorrect for two reasons: 1) The fact that attrs is non-NULL doesn’t necessarily mean that the node has attributes. It’s possible that it did at one point have attributes, but those were all removed. In such a case, attrsCount will be zero, but attrs will still be non-NULL. Have a look at the implementation of DFGetAttribute, DFSetAttribute, DFRemoveAttribute in DFDOM.c to see how attrs, attrsCount, and attrsAlloc are used. 2) If there are multiple attributes, this will only print the first. To go through all the attributes and print out their tags & values, you would use a loop: You can also use DFGetAttribute if you want to already know the tag you are looking for (e.g. TEXT_OUTLINE_LEVEL). This function will return NULL if the attribute does not exist, or the attribute value if it does. > Tag text_h(DFNode *node) > { > char *s = node->attrs->value; Referencing node->attrs->value is incorrect, as you don’t know whether the node will have any attributes, and it if does, whether the style name (which is what I assume you’re looking for here) will happen to be the first one. DFGetAttribute(node,TEXT_STYLE_NAME) is how you would get this reliably. G: Does not always happen so :( see TEXT_H entry for a failure (probably on my part :-) // TODO: Once this basic traversal is implemented and is capable of producing paragraphs, // tables, lists, and spans, add ids to the HTML elements as they are created. That is, set // the id attribute of each new HTML element to a string containing the idPrefix followed by Q: what is that idPrefix thing and how do I find/generate this? // the seqNo field of the node in contentDoc from which the HTML element was generated. Q: As in: adjust the automatic counter that works currently? Ok, but it'll leave holes in the count :( Note: I still found the translateXMLEnumName array informative, so I put it back again as a dev aid. */ /** * Temp function: Collect all the possible translations from ODF to * HTML. Will probably still change shape a lot. * * Input: DFNode from ODF document that is currently being examined. * * Returns: Tag with HTMl value or TAG_NOT_MATCHED, or, writes code to * screen that can be added to the switch function. (see default: ) */ Tag find_HTML(DFNode *odfNode, DFNode *htmlNode) { // I added a couple of #defines for dev purposes. // // TAG_NOT_MATCHED shows me stuff I know about but haven't managed // to match up. // // default sends back TAG_NOT_FOUND and so catches new tags and // helpfully prints out code for adding to the switch statement // ;-) // // for some weird reason, c-mode in emacs gives me a funky // indentation in switch functions. I'll fix it once this // function settled. printf(MAGENTA "find_HTML(): TAG NAME: %s Value: %d \n" RESET, translateXMLEnumName[odfNode->tag], odfNode->tag ); switch(odfNode->tag) { case TEXT_H : { //headers h1 - h6, h7+ returns as p const char* s = DFGetAttribute(odfNode,TEXT_STYLE_NAME); // Grab the very last digit. If it's a 0-5 we have a proper // header, otherwise, we have heading 6-10. int s_val = atoi(&s[strlen(s)-1]) - 1; if (s_val >= 0 && s_val < 6) return HTML_H1 + s_val; else return HTML_P; } // paragraph case TEXT_P : { return HTML_P; } // lists case TEXT_LIST : { return HTML_LIST; } case TEXT_LIST_ITEM : { return HTML_LI; } // tables case TABLE_TABLE : { return HTML_TABLE; } case TABLE_TABLE_COLUMN : { return HTML_COL; } case TABLE_TABLE_ROW : { return HTML_ROWS; } case TABLE_TABLE_CELL : { return TAG_NOT_MATCHED; } case STYLE_TABLE_CELL_PROPERTIES : { return TAG_NOT_MATCHED; } case STYLE_TABLE_COLUMN_PROPERTIES : { return TAG_NOT_MATCHED; } case STYLE_TABLE_PROPERTIES : { return TAG_NOT_MATCHED; } case STYLE_TEXT_PROPERTIES : { // no output: // const char* s = DFGetAttribute(odfNode,STYLE_TEXT_PROPERTIES); const char* s = DFGetAttribute(odfNode,DOM_TEXT); for (int i = 0; i < odfNode->attrsCount; i++) { if (odfNode->attrs[i].tag == FO_FONT_WEIGHT && !strcmp("bold",odfNode->attrs[i].value)) { DFCreateChildElement(htmlNode, HTML_B); return 0; } if (odfNode->attrs[i].tag == FO_FONT_STYLE && !strcmp("italic",odfNode->attrs[i].value)) { DFCreateChildElement(htmlNode, HTML_I); return 0; } if (odfNode->attrs[i].tag == STYLE_TEXT_UNDERLINE_STYLE) { DFCreateChildElement(htmlNode, HTML_U); return 0; } printf(RED "Failure: " RESET "tag %u tag name %s value %s\n", odfNode->attrs[i].tag, translateXMLEnumName[odfNode->attrs[i].tag], odfNode->attrs[i].value); } return TAG_NOT_MATCHED; } // document case OFFICE_AUTOMATIC_STYLES : { return TAG_NOT_MATCHED; } case OFFICE_BODY : { return TAG_NOT_MATCHED; } case OFFICE_FONT_FACE_DECLS : { return TAG_NOT_MATCHED; } case OFFICE_SCRIPTS : { return TAG_NOT_MATCHED; } case OFFICE_TEXT : { return TAG_NOT_MATCHED; } // fonts, styles'n'things. case STYLE_FONT_FACE : { return TAG_NOT_MATCHED; } case STYLE_STYLE : { return TAG_NOT_MATCHED; } case TEXT_SEQUENCE_DECL : { return TAG_NOT_MATCHED; } case TEXT_SEQUENCE_DECLS : { return TAG_NOT_MATCHED; } default: { // rm foo.html; make ; ./bin/dfconvert get bin/lists.odt foo.html | sort -u // ... because we are too lazy to type. printf("case %s : { return TAG_NOT_MATCHED; }\n", translateXMLEnumName[odfNode->tag]); return TAG_NOT_FOUND; } } } /** * Dev tool: List all the nodes following the given one. */ void show_nodes(DFNode *odfNode, int level) { printf("Level: %d\n",level); level++; print_node_info(odfNode); for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) { walkChildren(odfChild, level); } } /** * Dev tool: List all the nodes following the given one. */ void walkChildren(DFNode *odfNode, int level) { printf("Level: %d\n",level); level++; print_node_info(odfNode); for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) { walkChildren(odfChild, level); } } /** * Dev tool: List all the nodes below the given one. */ /*void show_nodes(DFNode *odfNode, int level) { DFNode *nextNode = odfNode; do { print_node_info(nextNode); nextNode = DFNextNode(nextNode); }while(nextNode != NULL); }*/ //give me the styles document void buildCSS_Styles(CSSSheet * cssSheet, DFNode *odfNode) { //walk through the nodes // go to the office:styles can we find it? //iterate each style:style // make a css // dip down to get its attributes printf("buildCSS_Styles\n"); printf("name = %s\n", translateXMLEnumName[odfNode->tag]); //manually play with the functions first /* CSSStyle* cssStyle = CSSSheetLookupElement(cssSheet, "elementName", "className", 1, 0); CSSProperties * localproperties = CSSStyleRule(cssStyle); CSSPut(localproperties,"font-weight","bold");*/ for (DFNode *odfChild = odfNode->first; odfChild != NULL; odfChild = odfChild->next) { if(odfChild->tag == OFFICE_STYLES) { printf("Processing office styles\n"); for (DFNode *styleNode = odfChild->first; styleNode != NULL; styleNode = styleNode->next) { if(styleNode->tag == STYLE_STYLE) { for (unsigned int i = 0; i < styleNode->attrsCount; i++) { Tag t = styleNode->attrs[i].tag; if(t == STYLE_NAME) { printf("Create CSS Properties for %s\n", styleNode->attrs[i].value); //if this is a heading look for the TEXT_OUTLINE_LEVEL // use the attrbute fetch thing... const char* outlevel = DFGetAttribute(styleNode, STYLE_DEFAULT_OUTLINE_LEVEL); CSSStyle* cssStyle = NULL; if(outlevel != NULL) { char hlevel[4] = "h"; hlevel[1] = outlevel[0]; hlevel[2] = 0; cssStyle = CSSSheetLookupElement(cssSheet, hlevel, styleNode->attrs[i].value, 1, 0); } else { cssStyle = CSSSheetLookupElement(cssSheet, "div", styleNode->attrs[i].value, 1, 0); } for (DFNode *styleInfo = styleNode->first; styleInfo != NULL; styleInfo = styleInfo->next) { if(styleInfo->tag == STYLE_TEXT_PROPERTIES) { //just looking for bolds as a first cut for (unsigned int i = 0; i < styleInfo->attrsCount; i++) { Tag t = styleInfo->attrs[i].tag; switch(t) { case FO_FONT_WEIGHT: { CSSProperties * localproperties = CSSStyleRule(cssStyle); CSSPut(localproperties,"font-weight",styleInfo->attrs[i].value); break; } case FO_FONT_SIZE: { CSSProperties * localproperties = CSSStyleRule(cssStyle); CSSPut(localproperties,"font-size",styleInfo->attrs[i].value); break; } case STYLE_FONT_NAME: { CSSProperties * localproperties = CSSStyleRule(cssStyle); CSSPut(localproperties,"font-family",styleInfo->attrs[i].value); break; } } } } else if(styleInfo->tag == STYLE_PARAGRAPH_PROPERTIES) { //TBD } } } } } } } } } /** * Dev tool: List everything about a Node that's fit to print.. */ void print_node_info(DFNode *n) { if (n == NULL) return; if (n->tag) printf("Tag tag: %zu name = %s\n",n->tag, translateXMLEnumName[n->tag]); printf("unsigned int seqNo: %d\n",n->seqNo); // printf("struct DFDocument *doc: %p\n",n->doc); if (n->js) printf("void *js: %p\n",n->js); if (n->changed) printf("int changed: %d\n",n->changed); if (n->childrenChanged) printf("int childrenChanged %d\n",n->childrenChanged); if (n->seqNoHashNext) printf("DFNode *seqNoHashNext %p\n", n->seqNoHashNext); DFNameMap *map = n->doc->map; const TagDecl *td = DFNameMapNameForTag(map,n->tag); const NamespaceDecl *ns = DFNameMapNamespaceForID(map,td->namespaceID); // Attributes if (n->tag >= MIN_ELEMENT_TAG) { for (unsigned int i = 0; i < n->attrsCount; i++) { Tag t = n->attrs[i].tag; const TagDecl *attrDecl = DFNameMapNameForTag(map,t); printf("iteration %d === tag: %d name: %s namespaceID = %d localName = %s\n", i, t, translateXMLEnumName[t], td->namespaceID, td->localName); } } if (ns->namespaceURI) printf("namespace URI = %s\n",ns->namespaceURI); if (td->localName) printf("local name = %s\n",td->localName); if (n->attrsCount) printf(RED "unsigned int attrsCount: %d \n" RESET,n->attrsCount); if (n->attrs) { // printf("DFAttribute *attrs: %p ",n->attrs); if (n->attrs->tag) printf(", Tag tags: %zu ",n->attrs->tag); if (n->attrs->value) printf(", char *value: %s ",n->attrs->value); printf(" Tag Name = %s\n", translateXMLEnumName[n->attrs->tag]); } for (int i = 0; i < n->attrsCount; i++) { printf(BLUE "attrsCount %d tag %u value %s\n" RESET, i, n->attrs[i].tag,n->attrs[i].value); } if (n->attrsAlloc) printf("unsigned int attrsAlloc: %d\n", n->attrsAlloc); if (n->target) printf("char *target: %s\n", n->target); if (n->value) printf("char *value: %s\n", n->value); } /** * Dev tool: List less info about a node than print_node_info(). */ char *node_id_info(DFNode *node) { const char *local_name = DFNodeName(node); //const char *namespace_URI = DFNodeURI(node); const char *enum_name = translateXMLEnumName[node->tag]; int len = strlen (local_name) + strlen(enum_name) + 30; //strlen( namespace_URI)+30; char *r = malloc(len); snprintf(r, len, "Tag name = %s DFNodeName: %s", // " DFNodeURI: %s", enum_name, local_name //namespace_URI ); return r; } /** * Dev tool: List some info about a missing tag, alone with some high * lighting for easy viewing spotting. */ char *missing_tag_info(DFNode *node) { char *inform = red("Tag not matched: "); char *facts = node_id_info(node); int len = strlen(inform)+strlen(facts)+2; char *r = malloc(len); snprintf(r, len, "%s%s", inform, facts); return r; } /** * Dev tool: A selection of snazzy lines because I watched too many serger vids. */ void print_line(int style) { if (!style) printf("=============================================================\n"); else if (style == 1) printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"); else if (style == 2) printf("=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=\n"); }