react-xml-renderer
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.0 • Public • Published

    react-xml-renderer

    this is a small react renderer which allows you to render arbitrary XML using JSX.

    usage

    see test/renderer.spec.tsx

    import renderXML, { XML, xmlElement } from 'react-xml-renderer';
    
    // you can create XML elements using the xmlElement helper:
    const Foo = xmlElement('foo');
    
    const fooBarJsx = <Foo asdf="123">bar</Foo>;
    
    // or use the XML proxy instead:
    const fooBarJsx2 = <XML.foo asdf="123">bar</XML.foo>;
    
    // render your JSX to an xml string:
    
    const fooBar = renderXML(fooBarJsx);
    const fooBar2 = renderXml(fooBarJsx2);
    
    console.assert(fooBar === fooBar2); // true

    why

    if you've ever thought of rendering XML with React, you might have realized you can use react-dom to render your JSX to a string instead of into a dom node:

    import React from 'react';
    import ReactDomServer from 'react-dom/server';
    
    const jsx = <p>I'm a string!</p>;
    
    const xml = ReactDomServer.renderToStaticMarkup(jsx);
    
    console.log(xml); // <p>I&#x27;m a string!</p>

    okay, cool. now let's start writing some non-html content like, say, an RSS feed:

    import React from 'react';
    import ReactDomServer from 'react-dom/server';
    
    const jsx = <rss version="2.0"></rss>;
    //                             ~~~~~~
    // error TS2339: Property 'rss' does not exist on type 'JSX.IntrinsicElements'.
    
    const xml = ReactDomServer.renderToStaticMarkup(jsx);
    
    console.log(xml);

    oops - typescript expects all lowercase components to be real HTML elements, as defined by JSX.IntrinsicElements from @types/react.

    we can work around this by defining our own react component:

    import React from 'react';
    import ReactDomServer from 'react-dom/server';
    
    const Rss = (props: Record<string, any>) => React.createElement('rss', props);
    
    const jsx = <Rss version="2.0"></Rss>;
    
    const xml = ReactDomServer.renderToStaticMarkup(jsx);
    
    console.log(xml); // <rss version="2.0"></rss>

    great, now we can build out the rest of our xml using this approach:

    import React from 'react';
    import ReactDomServer from 'react-dom/server';
    
    const xmlElement = (name: string) => (props: Record<string, any>) =>
    	React.createElement(name, props);
    
    const Rss = xmlElement('rss');
    const Channel = xmlElement('channel');
    const Title = xmlElement('title');
    const Description = xmlElement('description');
    const Link = xmlElement('link');
    const Copyright = xmlElement('copyright');
    const LastBuildDate = xmlElement('lastBuildDate');
    const PubDate = xmlElement('pubDate');
    const Ttl = xmlElement('ttl');
    const Item = xmlElement('item');
    const Guid = xmlElement('guid');
    
    const jsx = (
    	<Rss version="2.0">
    		<Channel>
    			<>
    				<Title>RSS Title</Title>
    				<Description>This is an example of an RSS feed</Description>
    				<Link>http://www.example.com/main.html</Link>
    				<Copyright>2020 Example.com All rights reserved</Copyright>
    				<LastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </LastBuildDate>
    				<PubDate>Sun, 06 Sep 2009 16:20:00 +0000</PubDate>
    				<Ttl>1800</Ttl>
    
    				<Item>
    					<Title>Example entry</Title>
    					<Description>
    						Here is some text containing an interesting Description.
    					</Description>
    					<Link>http://www.example.com/blog/post/1</Link>
    					<Guid isPermaLink="false">
    						7bd204c6-1655-4c27-aeee-53f933c5395f
    					</Guid>
    					<PubDate>Sun, 06 Sep 2009 16:20:00 +0000</PubDate>
    				</Item>
    			</>
    		</Channel>
    	</Rss>
    );
    
    const xml = ReactDomServer.renderToStaticMarkup(jsx);
    
    console.log(xml);

    this code doesn't trigger any typescript type errors! however, if we run it, we get a runtime error:

    Error: link is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.
    

    <link>, in HTML, is a void element, meaning it can't accept children.

    this shouldn't matter to us, because we're not writing HTML, we're writing XML. but react-dom has special checks to prevent us from writing invalid HTML which can't be disabled. if we want to create non-HTML from JSX, we need a different renderer.

    prior art

    react-xml-renderer is a stripped-down fork of react-tiny-dom, and uses jsdom behind-the-scenes.

    Install

    npm i react-xml-renderer

    DownloadsWeekly Downloads

    0

    Version

    1.0.0

    License

    MIT

    Unpacked Size

    21.5 kB

    Total Files

    22

    Last publish

    Collaborators

    • rettgerst