import: add support to import any xml tab element to XmlComponent (#8)

- make method to import/convert to XmlComponent
 - expose method to add childElement to Header/Footer
 - add tests
This commit is contained in:
h4buli
2018-05-28 09:15:44 +02:00
committed by GitHub
parent dadd8c122f
commit 97e976a184
5 changed files with 138 additions and 21 deletions

View File

@ -1,5 +1,52 @@
import { expect } from "chai";
import { ImportedXmlComponent } from "./";
import { ImportedXmlComponent, convertToXmlComponent } from "./";
const xmlString = `
<w:p w:one="value 1" w:two="value 2">
<w:rPr>
<w:noProof>some value</w:noProof>
</w:rPr>
<w:r active="true">
<w:t>Text 1</w:t>
</w:r>
<w:r active="true">
<w:t>Text 2</w:t>
</w:r>
</w:p>
`;
const importedXmlElement = {
"w:p": {
_attr: { "w:one": "value 1", "w:two": "value 2" },
"w:rPr": { "w:noProof": "some value" },
"w:r": [{ _attr: { active: "true" }, "w:t": "Text 1" }, { _attr: { active: "true" }, "w:t": "Text 2" }],
},
};
const convertedXmlElement = {
deleted: false,
rootKey: "w:p",
root: [
{
deleted: false,
rootKey: "w:rPr",
root: [{ deleted: false, rootKey: "w:noProof", root: ["some value"] }],
},
{
deleted: false,
rootKey: "w:r",
root: [{ deleted: false, rootKey: "w:t", root: ["Text 1"] }],
_attr: { active: "true" },
},
{
deleted: false,
rootKey: "w:r",
root: [{ deleted: false, rootKey: "w:t", root: ["Text 2"] }],
_attr: { active: "true" },
},
],
_attr: { "w:one": "value 1", "w:two": "value 2" },
};
describe("ImportedXmlComponent", () => {
let importedXmlComponent: ImportedXmlComponent;
@ -31,4 +78,16 @@ describe("ImportedXmlComponent", () => {
});
});
});
it("should create XmlComponent from xml string", () => {
const converted = ImportedXmlComponent.fromXmlString(xmlString);
expect(converted).to.eql(convertedXmlElement);
});
describe("convertToXmlComponent", () => {
it("should convert to xml component", () => {
const converted = convertToXmlComponent("w:p", importedXmlElement["w:p"]);
expect(converted).to.eql(convertedXmlElement);
});
});
});

View File

@ -1,4 +1,53 @@
import { XmlComponent, IXmlableObject } from ".";
import * as fastXmlParser from "fast-xml-parser";
import { flatMap } from "lodash";
export const parseOptions = {
ignoreAttributes: false,
attributeNamePrefix: "",
attrNodeName: "_attr",
};
/**
* Converts the given xml element (in json format) into XmlComponent.
* Note: If element is array, them it will return ImportedXmlComponent[]. Example for given:
* element = [
* { w:t: "val 1"},
* { w:t: "val 2"}
* ]
* will return
* [
* ImportedXmlComponent { rootKey: "w:t", root: [ "val 1" ]},
* ImportedXmlComponent { rootKey: "w:t", root: [ "val 2" ]}
* ]
*
* @param elementName name (rootKey) of the XmlComponent
* @param element the xml element in json presentation
*/
export function convertToXmlComponent(elementName: string, element: any): ImportedXmlComponent | ImportedXmlComponent[] {
const xmlElement = new ImportedXmlComponent(elementName, element._attr);
if (Array.isArray(element)) {
const out: any[] = [];
element.forEach((itemInArray) => {
out.push(convertToXmlComponent(elementName, itemInArray));
});
return flatMap(out);
} else if (typeof element === "object") {
Object.keys(element)
.filter((key) => key !== "_attr")
.map((item) => convertToXmlComponent(item, element[item]))
.forEach((converted) => {
if (Array.isArray(converted)) {
converted.forEach(xmlElement.push.bind(xmlElement));
} else {
xmlElement.push(converted);
}
});
} else if (element !== "") {
xmlElement.push(element);
}
return xmlElement;
}
/**
* Represents imported xml component from xml file.
@ -53,6 +102,23 @@ export class ImportedXmlComponent extends XmlComponent {
push(xmlComponent: XmlComponent) {
this.root.push(xmlComponent);
}
/**
* Converts the xml string to a XmlComponent tree.
*
* @param importedContent xml content of the imported component
*/
static fromXmlString(importedContent: string): ImportedXmlComponent {
const imported = fastXmlParser.parse(importedContent, parseOptions);
const elementName = Object.keys(imported)[0];
const converted = convertToXmlComponent(elementName, imported[elementName]);
if (Array.isArray(converted) && converted.length > 1) {
throw new Error("Invalid conversion, input must be one element.");
}
return Array.isArray(converted) ? converted[0] : converted;
}
}
/**