Safely passing XML string to Reactive HTML

Hi all,

I am having a xml that I need to pass it to Reactive HTML application. However, I am not pretty sure how to handle it correctly. I tried to decode xml string by using DOMParser().parseFromString(input, "text/html"), but there are some missing tags. As you can see in my xml below, it included <b /> tag that will be incorrectly interpreted and already missing if you see from console.log(data.xml).

Any suggestion for the best practice to deal with this xml string are greatly appreciated.

Thanks,
Arifin

xml="""<?xml version="1.0" encoding="UTF-8" ?>
<CDXML
><colortable>
<color r="1" g="1" b="1"/>
<color r="0" g="0" b="0"/>
<color r="1" g="0" b="0"/>
<color r="1" g="1" b="0"/>
<color r="0" g="1" b="0"/>
<color r="0" g="1" b="1"/>
<color r="0" g="0" b="1"/>
<color r="1" g="0" b="1"/>
</colortable><fonttable>
<font id="24" charset="utf-8" name="Arial"/>
<font id="25" charset="utf-8" name="Times New Roman"/>
</fonttable><page
 id="6184"
 BoundingBox="0 0 776 333"
 Width="776"
 Height="333"
 HeaderPosition="36"
 FooterPosition="36"
 PageOverlap="0"
 PrintTrimMarks="yes"
 HeightPages="1"
 WidthPages="1"
 DrawingSpace="poster"
><fragment
 id="6168"
 BoundingBox="333.52 127.42 386.48 188.58"
 Z="36"
><n
 id="6165"
 p="334.02 143"
 Z="33"
 AS="N"
/><n
 id="6167"
 p="334.02 173"
 Z="35"
 AS="N"
/><n
 id="6169"
 p="360 188"
 Z="37"
 AS="N"
/><n
 id="6171"
 p="385.98 173"
 Z="39"
 AS="N"
/><n
 id="6173"
 p="385.98 143"
 Z="41"
 AS="N"
/><n
 id="6175"
 p="360 128"
 Z="43"
 AS="N"
/><b
 id="6177"
 Z="45"
 B="6165"
 E="6167"
 Order="2"
 BS="N"
 BondCircularOrdering="6182 0 0 6178"
/><b
 id="6178"
 Z="46"
 B="6167"
 E="6169"
 BS="N"
/><b
 id="6179"
 Z="47"
 B="6169"
 E="6171"
 Order="2"
 BS="N"
 BondCircularOrdering="6178 0 0 6180"
/><b
 id="6180"
 Z="48"
 B="6171"
 E="6173"
 BS="N"
/><b
 id="6181"
 Z="49"
 B="6173"
 E="6175"
 Order="2"
 BS="N"
 BondCircularOrdering="6180 0 0 6182"
/><b
 id="6182"
 Z="50"
 B="6175"
 E="6165"
 BS="N"
/></fragment></page></CDXML>"""


from panel.reactive import ReactiveHTML
import panel as pn
import param

class XmlReader(ReactiveHTML):
    
    xml = param.String(default='')
    
    _template = """
    <div id="container">
    </div>
    """
    
    _scripts = {
        'render':   """
            function htmlDecode(input) {
              var doc = new DOMParser().parseFromString(input, "text/html");
              return doc.documentElement.textContent;
            }
            console.log(data.xml) 
            var decoded_xml = htmlDecode(data.xml)   
            console.log(decoded_xml) 
        """
    } 

xml_reader = XmlReader(xml=xml)
pn.extension()
xml_reader.servable()

Hi

I am not sure exactly what you are trying to achieve and why. Could you eleborate? That would help me help you :slight_smile:

Hi Marc. I am trying to use ChemdrawJS with ReactiveHTML. I would like to read the cdxml string (the example is given above) and show the structures with ChemdrawJS. However, since it require the license, I am not pretty sure to elaborate.

Let me go a bit detail about it. While I pass the data.xml to the script, I got the error due to wrong format. I checked it by using console.log and I found a problem that we got the escape HTML format in data.xml. Therefore, I decoded it by the htmlDecode function. However, another problem is that <b /> tags are missing which is related to the chemical bond information.

this is the code of htmlDecode

Before decoding (data.xml).

&lt;CDXML
&gt;&lt;colortable&gt;
&lt;color r="1" g="1" b="1"/&gt;
&lt;color r="0" g="0" b="0"/&gt;
&lt;color r="1" g="0" b="0"/&gt;
&lt;color r="1" g="1" b="0"/&gt;
&lt;color r="0" g="1" b="0"/&gt;
&lt;color r="0" g="1" b="1"/&gt;
&lt;color r="0" g="0" b="1"/&gt;
&lt;color r="1" g="0" b="1"/&gt;
&lt;/colortable&gt;&lt;fonttable&gt;
&lt;font id="24" charset="utf-8" name="Arial"/&gt;
&lt;font id="25" charset="utf-8" name="Times New Roman"/&gt;
&lt;/fonttable&gt;&lt;page
 id="6184"
 BoundingBox="0 0 776 333"
 Width="776"
 Height="333"
 HeaderPosition="36"
 FooterPosition="36"
 PageOverlap="0"
 PrintTrimMarks="yes"
 HeightPages="1"
 WidthPages="1"
 DrawingSpace="poster"
&gt;&lt;fragment
 id="6168"
 BoundingBox="333.52 127.42 386.48 188.58"
 Z="36"
&gt;&lt;n
 id="6165"
 p="334.02 143"
 Z="33"
 AS="N"
/&gt;&lt;n
 id="6167"
 p="334.02 173"
 Z="35"
 AS="N"
/&gt;&lt;n
 id="6169"
 p="360 188"
 Z="37"
 AS="N"
/&gt;&lt;n
 id="6171"
 p="385.98 173"
 Z="39"
 AS="N"
/&gt;&lt;n
 id="6173"
 p="385.98 143"
 Z="41"
 AS="N"
/&gt;&lt;n
 id="6175"
 p="360 128"
 Z="43"
 AS="N"
/&gt;<b><b><b><b><b><b>&lt;/fragment&gt;&lt;/page&gt;&lt;/CDXML&gt;</b></b></b></b></b></b>

After decoding with htmlDecode function.

<CDXML
><colortable>
<color r="1" g="1" b="1"/>
<color r="0" g="0" b="0"/>
<color r="1" g="0" b="0"/>
<color r="1" g="1" b="0"/>
<color r="0" g="1" b="0"/>
<color r="0" g="1" b="1"/>
<color r="0" g="0" b="1"/>
<color r="1" g="0" b="1"/>
</colortable><fonttable>
<font id="24" charset="utf-8" name="Arial"/>
<font id="25" charset="utf-8" name="Times New Roman"/>
</fonttable><page
 id="6184"
 BoundingBox="0 0 776 333"
 Width="776"
 Height="333"
 HeaderPosition="36"
 FooterPosition="36"
 PageOverlap="0"
 PrintTrimMarks="yes"
 HeightPages="1"
 WidthPages="1"
 DrawingSpace="poster"
><fragment
 id="6168"
 BoundingBox="333.52 127.42 386.48 188.58"
 Z="36"
><n
 id="6165"
 p="334.02 143"
 Z="33"
 AS="N"
/><n
 id="6167"
 p="334.02 173"
 Z="35"
 AS="N"
/><n
 id="6169"
 p="360 188"
 Z="37"
 AS="N"
/><n
 id="6171"
 p="385.98 173"
 Z="39"
 AS="N"
/><n
 id="6173"
 p="385.98 143"
 Z="41"
 AS="N"
/><n
 id="6175"
 p="360 128"
 Z="43"
 AS="N"
/></fragment></page></CDXML>

Hi Arifin

I don’t understand the comment about <b /> missing as I don’t see any <b /> in your code??

Why don’t this work?

xml="""
<CDXML
><colortable>
<color r="1" g="1" b="1"/>
<color r="0" g="0" b="0"/>
<color r="1" g="0" b="0"/>
<color r="1" g="1" b="0"/>
<color r="0" g="1" b="0"/>
<color r="0" g="1" b="1"/>
<color r="0" g="0" b="1"/>
<color r="1" g="0" b="1"/>
</colortable><fonttable>
<font id="24" charset="utf-8" name="Arial"/>
<font id="25" charset="utf-8" name="Times New Roman"/>
</fonttable><page
 id="6184"
 BoundingBox="0 0 776 333"
 Width="776"
 Height="333"
 HeaderPosition="36"
 FooterPosition="36"
 PageOverlap="0"
 PrintTrimMarks="yes"
 HeightPages="1"
 WidthPages="1"
 DrawingSpace="poster"
><fragment
 id="6168"
 BoundingBox="333.52 127.42 386.48 188.58"
 Z="36"
><n
 id="6165"
 p="334.02 143"
 Z="33"
 AS="N"
/><n
 id="6167"
 p="334.02 173"
 Z="35"
 AS="N"
/><n
 id="6169"
 p="360 188"
 Z="37"
 AS="N"
/><n
 id="6171"
 p="385.98 173"
 Z="39"
 AS="N"
/><n
 id="6173"
 p="385.98 143"
 Z="41"
 AS="N"
/><n
 id="6175"
 p="360 128"
 Z="43"
 AS="N"
/><b
 id="6177"
 Z="45"
 B="6165"
 E="6167"
 Order="2"
 BS="N"
 BondCircularOrdering="6182 0 0 6178"
/><b
 id="6178"
 Z="46"
 B="6167"
 E="6169"
 BS="N"
/><b
 id="6179"
 Z="47"
 B="6169"
 E="6171"
 Order="2"
 BS="N"
 BondCircularOrdering="6178 0 0 6180"
/><b
 id="6180"
 Z="48"
 B="6171"
 E="6173"
 BS="N"
/><b
 id="6181"
 Z="49"
 B="6173"
 E="6175"
 Order="2"
 BS="N"
 BondCircularOrdering="6180 0 0 6182"
/><b
 id="6182"
 Z="50"
 B="6175"
 E="6165"
 BS="N"
/></fragment></page></CDXML>"""


from panel.reactive import ReactiveHTML
import panel as pn
import param

class XmlReader(ReactiveHTML):

    xml = param.String(default='')

    _template = """
    <div id="my-element>hello</div>
    """

    _scripts = {
        'render':   """
            var encodedStr = data.xml;

            var parser = new DOMParser;
            var dom = parser.parseFromString(
                '<!doctype html><body>' + encodedStr,
                'text/html');
            var decodedString = dom.body.textContent;

            console.log(decodedString);
        """
    }

xml_reader = XmlReader(xml=xml)
pn.extension()
xml_reader.servable()

hi Marc, these 6 <b /> are missing. As in your code, these block also not obtained. Before decoding, data.xml only has <b><b><b><b><b><b>&lt;/fragment&gt;&lt;/page&gt;&lt;/CDXML&gt;</b></b></b></b></b></b> at the end. the information of <b /> also gone. I think it is because <b /> is used for bold in HTML.

1 Like

I think this is not the best solution, but this could be work. I am passing json string and change it back into xml with js.

import xmltodict, json
from panel.reactive import ReactiveHTML
import panel as pn
import param

o = xmltodict.parse(xml)
json_text=json.dumps(o)

class XmlReader(ReactiveHTML):
    
    xml = param.String(default='')
    
    _template = """
    <div id="container">
    </div>
    """
    
    _scripts = {
        'render':   """
            var data = data.xml
            var jsonObj = JSON.parse(data); 
            var xml = json2xml(jsonObj)
            console.log(xml) 
        """
    } 

    __javascript__ ={
        'http://goessner.net/download/prj/jsonxml/json2xml.js',
    }
xml_reader = XmlReader(xml=json_text)
pn.extension()
xml_reader.servable()
1 Like