This commit is contained in:
amitm02
2018-10-17 09:15:32 +03:00
parent 9d9dd62f00
commit 3f3fd05cb1
12 changed files with 94 additions and 147 deletions

View File

@ -1,24 +1,15 @@
import * as fastXmlParser from "fast-xml-parser";
import { xml2js, Element as XMLElement } from 'xml-js'
// var convertXmlJs = require('xml-js');
import * as JSZip from "jszip";
import { Element as XMLElement, ElementCompact as XMLElementCompact, xml2js } from "xml-js";
import { FooterReferenceType } from "file/document/body/section-properties/footer-reference";
import { HeaderReferenceType } from "file/document/body/section-properties/header-reference";
import { FooterWrapper, IDocumentFooter } from "file/footer-wrapper";
import { HeaderWrapper, IDocumentHeader } from "file/header-wrapper";
import { convertToXmlComponent, ImportedXmlComponent, parseOptions, convertToXmlComponentOld } from "file/xml-components";
import { convertToXmlComponent, ImportedXmlComponent } from "file/xml-components";
import { Styles } from "file/styles";
import { ExternalStylesFactory } from "file/styles/external-styles-factory";
const importParseOptions = {
...parseOptions,
textNodeName: "",
trimValues: false,
};
const schemeToType = {
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header": "header",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer": "footer",
@ -70,50 +61,46 @@ export class ImportDotx {
const headers: IDocumentHeader[] = [];
for (const headerRef of documentRefs.headers) {
const headerKey = "w:hdr";
const relationFileInfo = documentRelationships.find((rel) => rel.id === headerRef.id);
if (relationFileInfo === null || !relationFileInfo) {
throw new Error(`Can not find target file for id ${headerRef.id}`);
}
const xmlData = await zipContent.files[`word/${relationFileInfo.target}`].async("text");
const xmlObjOld = fastXmlParser.parse(xmlData, importParseOptions);
const xmlObj = xml2js(xmlData, {compact: false}) as XMLElement;
if (xmlObj.elements === undefined || xmlObj.elements[0].name !== headerKey) {
const xmlObj = xml2js(xmlData, { compact: false, captureSpacesBetweenElements: true }) as XMLElement;
let headerXmlElement: XMLElement | undefined;
for (const xmlElm of xmlObj.elements || []) {
if (xmlElm.name === "w:hdr") {
headerXmlElement = xmlElm;
}
}
if (headerXmlElement === undefined) {
continue;
}
console.log('=========== fast-xml-parser header =======');
console.log(JSON.stringify(xmlObjOld, null, 2));
console.log('=========== xml-js header =======');
console.log(JSON.stringify(xmlObj, null, 2));
const headerXmlElement = xmlObj.elements[0];
const importedComp = convertToXmlComponent(headerKey, headerXmlElement) as ImportedXmlComponent;
console.log('=========== importedComp header =======');
console.log(JSON.stringify(importedComp, null, 2));
const importedCompOld = convertToXmlComponentOld(headerKey, xmlObjOld[headerKey]) as ImportedXmlComponent;
console.log('=========== importedCompOld header =======');
console.log(JSON.stringify(importedCompOld, null, 2));
const header = new HeaderWrapper(this.currentRelationshipId++, importedCompOld);
// const header = new HeaderWrapper(this.currentRelationshipId++, importedComp);
const importedComp = convertToXmlComponent(headerXmlElement) as ImportedXmlComponent;
const header = new HeaderWrapper(this.currentRelationshipId++, importedComp);
await this.addRelationToWrapper(relationFileInfo, zipContent, header);
headers.push({ type: headerRef.type, header });
}
const footers: IDocumentFooter[] = [];
for (const footerRef of documentRefs.footers) {
const footerKey = "w:ftr";
const relationFileInfo = documentRelationships.find((rel) => rel.id === footerRef.id);
if (relationFileInfo === null || !relationFileInfo) {
throw new Error(`Can not find target file for id ${footerRef.id}`);
}
const xmlData = await zipContent.files[`word/${relationFileInfo.target}`].async("text");
const xmlObj = fastXmlParser.parse(xmlData, importParseOptions);
const importedComp = convertToXmlComponent(footerKey, xmlObj[footerKey]) as ImportedXmlComponent;
const xmlObj = xml2js(xmlData, { compact: false, captureSpacesBetweenElements: true }) as XMLElement;
let footerXmlElement: XMLElement | undefined;
for (const xmlElm of xmlObj.elements || []) {
if (xmlElm.name === "w:ftr") {
footerXmlElement = xmlElm;
}
}
if (footerXmlElement === undefined) {
continue;
}
const importedComp = convertToXmlComponent(footerXmlElement) as ImportedXmlComponent;
const footer = new FooterWrapper(this.currentRelationshipId++, importedComp);
await this.addRelationToWrapper(relationFileInfo, zipContent, footer);
footers.push({ type: footerRef.type, footer });
@ -152,16 +139,19 @@ export class ImportDotx {
}
public findReferenceFiles(xmlData: string): IRelationshipFileInfo[] {
const xmlObj = fastXmlParser.parse(xmlData, importParseOptions);
const xmlObj = xml2js(xmlData, { compact: true }) as XMLElementCompact;
const relationXmlArray = Array.isArray(xmlObj.Relationships.Relationship)
? xmlObj.Relationships.Relationship
: [xmlObj.Relationships.Relationship];
const relations: IRelationshipFileInfo[] = relationXmlArray
.map((item) => {
.map((item: XMLElementCompact) => {
if (item._attributes === undefined) {
throw Error("relationship element has no attributes");
}
return {
id: this.parseRefId(item._attr.Id),
type: schemeToType[item._attr.Type],
target: item._attr.Target,
id: this.parseRefId(item._attributes.Id as string),
type: schemeToType[item._attributes.Type as string],
target: item._attributes.Target as string,
};
})
.filter((item) => item.type !== null);
@ -169,14 +159,11 @@ export class ImportDotx {
}
public extractDocumentRefs(xmlData: string): IDocumentRefs {
interface IAttributedXML {
_attr: object;
}
const xmlObj = fastXmlParser.parse(xmlData, importParseOptions);
const xmlObj = xml2js(xmlData, { compact: true }) as XMLElementCompact;
const sectionProp = xmlObj["w:document"]["w:body"]["w:sectPr"];
const headerProps: undefined | IAttributedXML | IAttributedXML[] = sectionProp["w:headerReference"];
let headersXmlArray: IAttributedXML[];
const headerProps: XMLElementCompact = sectionProp["w:headerReference"];
let headersXmlArray: XMLElementCompact[];
if (headerProps === undefined) {
headersXmlArray = [];
} else if (Array.isArray(headerProps)) {
@ -185,14 +172,17 @@ export class ImportDotx {
headersXmlArray = [headerProps];
}
const headers = headersXmlArray.map((item) => {
if (item._attributes === undefined) {
throw Error("header referecne element has no attributes");
}
return {
type: item._attr["w:type"],
id: this.parseRefId(item._attr["r:id"]),
type: item._attributes["w:type"] as HeaderReferenceType,
id: this.parseRefId(item._attributes["r:id"] as string),
};
});
const footerProps: undefined | IAttributedXML | IAttributedXML[] = sectionProp["w:footerReference"];
let footersXmlArray: IAttributedXML[];
const footerProps: XMLElementCompact = sectionProp["w:footerReference"];
let footersXmlArray: XMLElementCompact[];
if (footerProps === undefined) {
footersXmlArray = [];
} else if (Array.isArray(footerProps)) {
@ -202,9 +192,12 @@ export class ImportDotx {
}
const footers = footersXmlArray.map((item) => {
if (item._attributes === undefined) {
throw Error("footer referecne element has no attributes");
}
return {
type: item._attr["w:type"],
id: this.parseRefId(item._attr["r:id"]),
type: item._attributes["w:type"] as FooterReferenceType,
id: this.parseRefId(item._attributes["r:id"] as string),
};
});
@ -212,7 +205,7 @@ export class ImportDotx {
}
public titlePageIsDefined(xmlData: string): boolean {
const xmlObj = fastXmlParser.parse(xmlData, importParseOptions);
const xmlObj = xml2js(xmlData, { compact: true }) as XMLElementCompact;
const sectionProp = xmlObj["w:document"]["w:body"]["w:sectPr"];
return sectionProp["w:titlePg"] !== undefined;
}