Koperwiek
Koperwiek

Reputation: 13

transforming XML with XSLT gives a wrong result

I want to transform a two item XML to a two line piece of HTML

from lxml import etree


xroot = etree.XML(b'''<?xml version="1.0" encoding="utf-8"?>
    <xml>
        <name>donald</name>
        <surname>trump</surname>
    </xml>
    ''')
xml=etree.ElementTree(xroot)
xslt_root = etree.XML('''
     <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:template match="xml">
             <div id='name'><xsl:value-of select="name" /></div>
             <div id='surname'><xsl:value-of select="surname" /></div>
         </xsl:template>
 </xsl:stylesheet>''')
transform = etree.XSLT(xslt_root)
transform=etree.XSLT(xslt_root)
html=etree.tostring(transform(xml)).decode('utf-8')
print(html)

The result that I expect is:

 <div id='name'>donald</div>
 <div id='surname'>trump</div>

But the result I get is:

 <div id='name'>donald</div>

Why??

Upvotes: 0

Views: 272

Answers (2)

Daniel Haley
Daniel Haley

Reputation: 52878

It's probably because the result of your transformation is not well-formed XML (because you don't have a single root element; you have two div elements).

Passing the not well-formed XML to tostring(), which expects an element (singular) or tree, appears to be the reason you're only seeing the first result element.

If you wrap the divs in a single element (like test), you'll see both divs...

from lxml import etree

xroot = etree.XML(b'''<?xml version="1.0" encoding="utf-8"?>
    <xml>
        <name>donald</name>
        <surname>trump</surname>
    </xml>
    ''')
xml = etree.ElementTree(xroot)
xslt_root = etree.XML('''
     <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:template match="xml">
             <test>
                 <div id='name'><xsl:value-of select="name" /></div>
                 <div id='surname'><xsl:value-of select="surname" /></div>
             </test>
         </xsl:template>
 </xsl:stylesheet>''')
transform = etree.XSLT(xslt_root)
html = etree.tostring(transform(xml)).decode('utf-8')
print(html)

Print output...

<test><div id="name">donald</div><div id="surname">trump</div></test>

Just printing the result of the transform (print(transform(xml))) also shows both divs (with no changes to the XSLT).

Upvotes: 2

Yassine Addi
Yassine Addi

Reputation: 343

i'm not exactly aware of the reason, but what about doing this

from lxml import etree

xroot = etree.XML(b'''<?xml version="1.0" encoding="utf-8"?>
    <xml>
        <name>donald</name>
        <surname>trump</surname>
    </xml>
    ''')
xml = etree.ElementTree(xroot)
xslt_root = etree.XML('''
     <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:template match="xml">
             <div id='name'><xsl:value-of select="name" /></div>
             <div id='surname'><xsl:value-of select="surname" /></div>
         </xsl:template>
 </xsl:stylesheet>''')
# transform = etree.XSLT(xslt_root)
transform = etree.XSLT(xslt_root)
# html = etree.tostring(transform(xml)).decode('utf-8')
# print(html)
print(str(transform(xml)).split('\n'))
# ['<?xml version="1.0"?>', '<div id="name">donald</div><div id="surname">trump</div>', '']
# the element at index 1 contains <div id="name">donald</div><div id="surname">trump</div>

Upvotes: -1

Related Questions