https://medium.com/@mair.swartz/creating-xml-document-with-react-c6c37f5c608b
I wanted to see if React could be used to compose anything more then html documents or native applications. There are thousands of applications out there that use there own domain specific structure. These are often presented in XML format.
It turns out not to be too difficult to create XML documents using React and node. In this article I will create a very simple node application that spits out some xml using react from scratch.
Project setup
the following commands will set up an absolute minimal project to explore the concepts. I’m not going to spend too much time explaining these steps as they should be fairly intuitive
# make a directory
mkdir react-to-xml# cd into it
cd react-to-xml# initialise a node app
npm init -y# install react dependencies
npm install --save react react-dom
Even though the application never renders html elements, we still install react-dom because it has an ability to convert a react tree to a string but more on that later.
# install react dev dependencies
npm install --save-dev babel-cli babel-preset-react
Node applications don’t understand jsx so we will use the babel-cli to transpile our code into something node can understand using the react preset. In a real application you may want more presets and a webpack config file. but for the sake of simplicity I’m not doing that here
open up the package.json file and add the following command under the scripts section
"scripts": {
"start": "babel original.js --out-file server.js --presets=react && node server.js"
}
the file we will be working with is called original.js and babel will convert that to a server.js file which will then be run by node.
creating an xml structure
Im going to create an xml structure that looks like this
<pets>
<owner name="Neal">
<animal type="guinea pig" name="Sparkles" />
</owner>
<owner name="Luke">
<animal type="guinea pig" name="Wendy" />
<animal type="guinea pig" name="Renel" />
</owner>
</pets>
base elements
React has the ability to create an element using the React.createElement funcion. These are instances of an element. where the first argument is the actual element, the second argument are the properties and the third are child elements see React.createElement.
to see this in action let’s write the following in our original.js file
const React = require("react");const element = React.createElement("animal", {type: "guinea pig", name: "Sparkles"})console.log(element);
and then in our terminal we run
npm start
we get an object representation of this node that looks looks like this
{ ‘$$typeof’: Symbol(react.element),
type: ‘animal’,
key: null,
ref: null,
props: { type: ‘guinea pig’, name: ‘Sparkles’ },
_owner: null,
_store: {} }
make it an xml node
to convert this into an xml we can use the react-dom/server module which has a renderToStaticMarkup function. Change the code as follows and run the app (using npm start)
const React = require("react");
const ReactDomServer = require("react-dom/server")const element = React.createElement("animal", {type: "guinea pig", name: "Sparkles"})
const elementXML = ReactDomServer.renderToStaticMarkup(element)console.log(elementXML);
now we get
<animal type=”guinea pig” name=”Sparkles”></animal>
As previously mentioned this is an instance of a node but, what I want is an abstraction so I can have a reusable jsx elements. This can be accomplished using a React’s stateless component. like so
const Animal = (props) => React.createElement(“animal”, props)
we can rewrite our file to look like this
const React = require("react");
const ReactDomServer = require("react-dom/server")const Animal = (props) => React.createElement("animal", props)
const elementXML = ReactDomServer.renderToStaticMarkup(
<Animal type="guinea pig" name="Sparkles" />
)console.log(elementXML);
running the app gives us the same output as before
rendering child elements
We have our animal element done. lets do the “owner”
const React = require("react");
const ReactDomServer = require("react-dom/server");const Animal = (props) => React.createElement("animal", props);
const Owner = (props) => React.createElement("Owner", props);const elementXML = ReactDomServer.renderToStaticMarkup(
<Owner name="Luke">
<Animal type="guinea pig" name="Sparkles" />
</Owner>
)console.log(elementXML);
the output as follows…
<Owner name="Luke">
<Animal type="guinea pig" name="Sparkles" />
</Owner>
It turns out that we don’t need to do anything fancy for React.CreateElements third argument (children) because children are passed in as props.
finally lets create our root element and wrap this up.
full listing as follows…
const React = require("react");
const ReactDomServer = require("react-dom/server")const Animal = (props) => React.createElement("animal", props);
const Owner = (props) => React.createElement("owner", props);
const Pets = (props) => React.createElement("pets", props);const elementXML = ReactDomServer.renderToStaticMarkup(
<Pets>
<Owner name="Luke">
<Animal type="guinea pig" name="Sparkles" />
</Owner>
<owner name="Neal">
<Animal type="guinea pig" name="Wendy" />
<Animal type="guinea pig" name="Renel" />
</owner>
</Pets>
)console.log(elementXML);
check that out! our code looks exactly like the original required xml. what a coincidence and in this case so does the output
This is a fairly trivial example and has loads of room for improvements including property and children validation, state changes, etc.
I leave it to you to think about where you could use this. one interesting application might be creating excel or word documents as they are just xml documents. if you don’t believe me take an excel file and rename its extension from an xls to a zip file and extract it.
Happy coding!