Skip to content

Latest commit

 

History

History
465 lines (398 loc) · 10.7 KB

3.XMLBuilder.md

File metadata and controls

465 lines (398 loc) · 10.7 KB

XML Builder can be used to parse a JS object into XML. It supports following options;

const {XMLBuilder} = require('fast-xml-parser');

const options = {
    ignoreAttributes : false
};

const builder = new XMLBuilder(options);
let xmlDataStr = builder.build(jObj);

arrayNodeName

When you build XML from an array, it's better to set arrayNodeName option to some name.

const cars = [
    {
        "color": "purple",
        "type": "minivan",
        "registration": "2020-02-03",
        "capacity": 7
        },
        {
        "color": "orange",
        "type": "SUV",
        "registration": "2021-05-17",
        "capacity": 4
        },
];
const builder = new XMLBuilder({
    arrayNodeName: "car"
});
const output = builder.build(cars);
<car>
    <color>purple</color>
    <type>minivan</type>
    <registration>2020-02-03</registration>
    <capacity>7</capacity>
</car>
<car>
    <color>orange</color>
    <type>SUV</type>
    <registration>2021-05-17</registration>
    <capacity>4</capacity>
</car>

attributeNamePrefix

To recognize attribute properties in the JS object so that they can be trimmed.

attributesGroupName

To recognize attribute properties group in the JS object so that they can be trimmed and can form attribute expresstion for a tag.

This property is not supported when preserveOrder: true because attributes are already grouped.

attributeValueProcessor

To customize the bahaviour of parsing an attribute value to the string value. It accepts attribute name and value.

cdataPropName

To recognize CDATA properties in a JS object so that they can be transformed correcty.

Eg Input

{
            "any_name": {
                "person": {
                    "phone": [
                        122233344550,
                        122233344551,
                        ""
                    ],
                    "name":  [
                        "<some>Jack</some>Jack",
                        "<some>Mohan</some>"
                    ],
                    "blank": "",
                    "regx":  "^[ ].*$"
                }
            }
        };

code

const options = {
    processEntities:false,
    format: true,
    ignoreAttributes: false,
    cdataPropName: "phone"
};

const builder = new XMLBuilder(options);
const xmlOutput = builder.build(input);

Output

 <any_name>
    <person>
        <![CDATA[122233344550]]>
        <![CDATA[122233344551]]>
        <![CDATA[]]>
        <name><some>Jack</some>Jack</name>
        <name><some>Mohan</some></name>
        <blank></blank>
        <regx>^[ ].*$</regx>
    </person>
</any_name>`;

It is recommended to use preserveOrder: true when you're parsing XML to js object and building the XML back. So that the order of CDATA is maintained.

commentPropName

To recognize comments in a JS object so that they can be transformed correcty.

Eg Input

{
            "any_name": {
                "person": {
                    "phone": [
                        122233344550,
                        122233344551,
                        ""
                    ],
                    "name":  [
                        "<some>Jack</some>Jack",
                        "<some>Mohan</some>"
                    ],
                    "blank": "",
                    "regx":  "^[ ].*$"
                }
            }
        };

code

const options = {
    processEntities:false,
    format: true,
    ignoreAttributes: false,
    commentPropName: "phone"
};

const builder = new XMLBuilder(options);
const xmlOutput = builder.build(input);

Output

 <any_name>
    <person>
        <!--122233344550-->
        <!--122233344551-->
        <!---->
        <name><some>Jack</some>Jack</name>
        <name><some>Mohan</some></name>
        <blank></blank>
        <regx>^[ ].*$</regx>
    </person>
</any_name>`;

It is recommended to use preserveOrder: true when you're parsing XML to js object and building the XML back. So that the order of comment is maintained.

format

By default, parsed XML is single line XML string. By format: true, you can format it for better view.

ignoreAttributes

Don't consider attributes while building XML. Other attributes related properties should be set to correctly identifying an attribute property.

indentBy

Applicable only if format:true is set.

preserveOrder

When you parse a XML using XMLParser with preserveOrder: true, the result JS object has different structure. So parse that structure in original XML, you should set the same option while building the XML from that js object.

processEntities

Set it to true (default) to process XML entities. Check Entities section for more detail. If you don't have entities in your XML document then it is recommanded to disable it processEntities: false for better performance.

oneListGroup

This property group all the children tags in single parent tag.

{
    "Attributes": [
        {
            "Attribute": "1"
        },
        {
            "Attribute": "2"
        }
    ]
}
const builder = new XMLBuilder({oneListGroup:"true"})
const output = builder.build(json)

Output

<Attributes>
    <Attribute>1</Attribute>
    <Attribute>2</Attribute>
</Attributes>

stopNodes

As you set stopNodes to the XML parser configuration to avoid parsing and processing of any tag, you can set it builder to avoid parsing and entity processing. Check HTML Document Parsing for more detail.

This property is currently supported with preserveOrder: true option only.

suppressBooleanAttributes

You can parse attributes with value true without their value.

Input

const jsOrderedObj = [
    {
        "?textinfo": [
            {
                "#text": ""
            }
        ],
        ":@": {
            "@_whitespace": true,
            "@_is": true,
            "@_allowed": true
        }
    }
];
const options = {
    ignoreAttributes: false,
    preserveOrder: true,
    allowBooleanAttributes: true,
    suppressBooleanAttributes: true
};
const builder = new XMLBuilder(options);
const output = builder.build(result);

Outout

<?textinfo   whitespace is allowed?>

suppressEmptyNode

Tags with no text value would be parsed as empty tags. Input

const builder = new XMLBuilder({
    arrayNodeName: "any", //not effective
    suppressEmptyNode: true
});
const output = builder.build({
    a: 32,
    b: ""
});

Outout

<a>32</a>
<b/>

suppressUnpairedNode

To supress an unpared tag from <br/> to <br>.

tagValueProcessor

To customize the bahaviour of parsing the text value of a tag to the string value. It accepts tag name and value.

textNodeName

To recognize text value for a tag in the JS object so that they can be properly assigned to the tag.

unpairedTags

Unpaired Tags are the tags which don't have matching closing tag. Eg <br> in HTML. You can parse unpaired tags by providing their list to the parser, validator and builder.

Eg

const xmlData = `
    <rootNode>
        <tag>value</tag>
        <empty />
        <unpaired>
        <unpaired />
        <unpaired></unpaired>
    </rootNode>`;  

const options = {
    // suppressUnpairedNode: true,
    unpairedTags: ["unpaired"]
};
const parser = new XMLParser(options);
const result = parser.parse(xmlDataStr);

const builder = new XMLBuilder(options);
const output = builder.build(result);

Output

<rootNode>
  <tag>value</tag>
  <empty></empty>
  <unpaired>
  <unpaired>
  <unpaired>
</rootNode>

Now if you set `suppressUnpairedNode: false`. You'll get following output

```xml
<rootNode>
  <tag>value</tag>
  <empty></empty>
  <unpaired/>
  <unpaired/>
  <unpaired/>
</rootNode>

Restoring original XML

Example 1

When you use XML Parser with alwaysCreateTextNode: true, it doesn't impact XMLBuilder result

   const XMLdata = `
      <car>
        <color>purple</color>
        <type>minivan</type>
        <registration>2020-02-03</registration>
        <capacity>7</capacity>
      </car>`;

      const parser = new XMLParser({
          alwaysCreateTextNode: true,
      });
      let result = parser.parse(XMLdata);
      // console.log(JSON.stringify(result, null,4));

      const builder = new XMLBuilder({ format: true });
      const output = builder.build(result);

Output

<car>
  <color>purple</color>
  <type>minivan</type>
  <registration>2020-02-03</registration>
  <capacity>7</capacity>
</car>

Example 2

When you use XML Parser with isArray, it doesn't impact XMLBuilder result under some extent.

   const XMLdata = `
      <car>
        <color>purple</color>
        <type>minivan</type>
        <registration>2020-02-03</registration>
        <capacity>7</capacity>
      </car>`;

      const parser = new XMLParser({
          isArray: (tagName, jPath, isLeafNode, isAttribute) => {
          if(isLeafNode) return true;
        }
      });
      let result = parser.parse(XMLdata);
      // console.log(JSON.stringify(result, null,4));

      const builder = new XMLBuilder();
      const output = builder.build(result);

Output

<car>
  <color>purple</color>
  <type>minivan</type>
  <registration>2020-02-03</registration>
  <capacity>7</capacity>
</car>

Example 3

When you use XML Parser with preserveOrder, you should use the same option with XMLBuilder.

   const XMLdata = `
      <car>
        <color>purple</color>
        <type>minivan</type>
        <registration>2020-02-03</registration>
        <capacity>7</capacity>
      </car>`;

      const parser = new XMLParser({
          preserveOrder: true
      });
      let result = parser.parse(XMLdata);
      // console.log(JSON.stringify(result, null,4));

      const builder = new XMLBuilder({ preserveOrder: true });
      const output = builder.build(result);

Output

<car>
  <color>purple</color>
  <type>minivan</type>
  <registration>2020-02-03</registration>
  <capacity>7</capacity>
</car>

Example 4

You should set attributeNamePrefix and other properties to the same value for XML Parser and XMLBuilder.

const XMLdata = `
<car>
    <color alpha="7">purple</color>
    <type>minivan</type>
    <registration>2020-02-03</registration>
    <capacity>7</capacity>
</car>`;

const options = {
    ignoreAttributes: false,
    attributeNamePrefix: "@@",
    format: true
};
const parser = new XMLParser(options);
let result = parser.parse(XMLdata);
// console.log(JSON.stringify(result, null,4));

const builder = new XMLBuilder(options);
const output = builder.build(result);

Output

<car>
  <color alpha="7">purple</color>
  <type>minivan</type>
  <registration>2020-02-03</registration>
  <capacity>7</capacity>
</car>

> Next: XmlValidator