| #include "xmb.h" | 
 |  | 
 | #include "file_utils.h" | 
 | #include "localize.h" | 
 | #include "ValuesFile.h" | 
 | #include "XMLHandler.h" | 
 | #include "XLIFFFile.h" | 
 |  | 
 | #include <map> | 
 | #include <cstdio> | 
 |  | 
 | using namespace std; | 
 |  | 
 | const char *const NS_MAP[] = { | 
 |     "xml", XMLNS_XMLNS, | 
 |     NULL, NULL | 
 | }; | 
 |  | 
 | set<string> g_tags; | 
 |  | 
 | static string | 
 | strip_newlines(const string& str) | 
 | { | 
 |     string res; | 
 |     const size_t N = str.length(); | 
 |     for (size_t i=0; i<N; i++) { | 
 |         char c = str[i]; | 
 |         if (c != '\n' && c != '\r') { | 
 |             res += c; | 
 |         } else { | 
 |             res += ' '; | 
 |         } | 
 |     } | 
 |     return res; | 
 | } | 
 |  | 
 | static int | 
 | rename_id_attribute(XMLNode* node) | 
 | { | 
 |     vector<XMLAttribute>& attrs = node->EditAttributes(); | 
 |     const size_t I = attrs.size(); | 
 |     for (size_t i=0; i<I; i++) { | 
 |         XMLAttribute attr = attrs[i]; | 
 |         if (attr.name == "id") { | 
 |             attr.name = "name"; | 
 |             attrs.erase(attrs.begin()+i); | 
 |             attrs.push_back(attr); | 
 |             return 0; | 
 |         } | 
 |     } | 
 |     return 1; | 
 | } | 
 |  | 
 | static int | 
 | convert_xliff_to_ph(XMLNode* node, int* phID) | 
 | { | 
 |     int err = 0; | 
 |     if (node->Type() == XMLNode::ELEMENT) { | 
 |         if (node->Namespace() == XLIFF_XMLNS) { | 
 |             g_tags.insert(node->Name()); | 
 |             node->SetName("", "ph"); | 
 |  | 
 |             err = rename_id_attribute(node); | 
 |             if (err != 0) { | 
 |                 char name[30]; | 
 |                 (*phID)++; | 
 |                 sprintf(name, "id-%d", *phID); | 
 |                 node->EditAttributes().push_back(XMLAttribute("", "name", name)); | 
 |                 err = 0; | 
 |             } | 
 |         } | 
 |         vector<XMLNode*>& children = node->EditChildren(); | 
 |         const size_t I = children.size(); | 
 |         for (size_t i=0; i<I; i++) { | 
 |             err |= convert_xliff_to_ph(children[i], phID); | 
 |         } | 
 |     } | 
 |     return err; | 
 | } | 
 |  | 
 | XMLNode* | 
 | resource_to_xmb_msg(const StringResource& res) | 
 | { | 
 |     // the msg element | 
 |     vector<XMLAttribute> attrs; | 
 |     string name = res.pos.file; | 
 |     name += ":"; | 
 |     name += res.TypedID(); | 
 |     attrs.push_back(XMLAttribute("", "name", name)); | 
 |     attrs.push_back(XMLAttribute("", "desc", strip_newlines(res.comment))); | 
 |     attrs.push_back(XMLAttribute(XMLNS_XMLNS, "space", "preserve")); | 
 |     XMLNode* msg = XMLNode::NewElement(res.pos, "", "msg", attrs, XMLNode::EXACT); | 
 |  | 
 |     // the contents are in xliff/html, convert it to xliff | 
 |     int err = 0; | 
 |     XMLNode* value = res.value; | 
 |     string tag = value->Name(); | 
 |     int phID = 0; | 
 |     for (vector<XMLNode*>::const_iterator it=value->Children().begin(); | 
 |             it!=value->Children().end(); it++) { | 
 |         err |= convert_html_to_xliff(*it, tag, msg, &phID); | 
 |     } | 
 |  | 
 |     if (err != 0) { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     // and then convert that to xmb | 
 |     for (vector<XMLNode*>::iterator it=msg->EditChildren().begin(); | 
 |             it!=msg->EditChildren().end(); it++) { | 
 |         err |= convert_xliff_to_ph(*it, &phID); | 
 |     } | 
 |  | 
 |     if (err == 0) { | 
 |         return msg; | 
 |     } else { | 
 |         return NULL; | 
 |     } | 
 | } | 
 |  | 
 | int | 
 | do_xlb_export(const string& outfile, const vector<string>& resFiles) | 
 | { | 
 |     int err = 0; | 
 |  | 
 |     size_t totalFileCount = resFiles.size(); | 
 |  | 
 |     Configuration english; | 
 |         english.locale = "en_US"; | 
 |  | 
 |     set<StringResource> allResources; | 
 |  | 
 |     const size_t J = resFiles.size(); | 
 |     for (size_t j=0; j<J; j++) { | 
 |         string resFile = resFiles[j]; | 
 |  | 
 |         ValuesFile* valuesFile = get_local_values_file(resFile, english, CURRENT_VERSION, "", true); | 
 |         if (valuesFile != NULL) { | 
 |             set<StringResource> resources = valuesFile->GetStrings(); | 
 |             allResources.insert(resources.begin(), resources.end()); | 
 |         } else { | 
 |             fprintf(stderr, "error reading file %s\n", resFile.c_str()); | 
 |         } | 
 |  | 
 |         delete valuesFile; | 
 |     } | 
 |  | 
 |     // Construct the XLB xml | 
 |     vector<XMLAttribute> attrs; | 
 |     attrs.push_back(XMLAttribute("", "locale", "en")); | 
 |     XMLNode* localizationbundle = XMLNode::NewElement(GENERATED_POS, "", "localizationbundle", | 
 |             attrs, XMLNode::PRETTY); | 
 |  | 
 |     for (set<StringResource>::iterator it=allResources.begin(); it!=allResources.end(); it++) { | 
 |         XMLNode* msg = resource_to_xmb_msg(*it); | 
 |         if (msg) { | 
 |             localizationbundle->EditChildren().push_back(msg); | 
 |         } else { | 
 |             err = 1; | 
 |         } | 
 |     } | 
 |  | 
 | #if 0 | 
 |     for (set<string>::iterator it=g_tags.begin(); it!=g_tags.end(); it++) { | 
 |         printf("tag: %s\n", it->c_str()); | 
 |     } | 
 |     printf("err=%d\n", err); | 
 | #endif | 
 |     if (err == 0) { | 
 |         FILE* f = fopen(outfile.c_str(), "wb"); | 
 |         if (f == NULL) { | 
 |             fprintf(stderr, "can't open outputfile: %s\n", outfile.c_str()); | 
 |             return 1; | 
 |         } | 
 |         fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); | 
 |         fprintf(f, "%s\n", localizationbundle->ToString(NS_MAP).c_str()); | 
 |         fclose(f); | 
 |     } | 
 |  | 
 |     return err; | 
 | } | 
 |  |