Parse an XML file to get a full tag by using Python's lxml package
Question: I've got the following XML file:

    
    
    <root>
    
        <scene name="scene1">
            <view ath="0" atv="10"/>
            <image url="img1.jgp"/>
            <hotspot name="hot1"/>
        </scene>
    
        <scene name="scene2">
            <view ath="20" atv="10"/>
            <image url="img2.jgp"/>
            <hotspot name="hot2"/>
        </scene>
    
    </root>
    

I'm writing a Python script using lxml package, to get the entire `view` tag
within `scene1`. That is:

    
    
    <view ath="0" atv="10" />
    

I've read the lxml documentation but all I can find is how to get the tag, its
attributes or its content, but not the entire tag.

Can anybody at least point me in the right direction? Does lxml has a function
or a method to achieve this?

Thanks,

Rafael


Answer: Your given XML source contains some errors; I fixed those, see my source
below:

    
    
    from lxml import etree
    
    source = """
    <root>
      <scene name="scene1">
        <view ath="0" atv="10" />
        <image url="img1.jgp" />
        <hotspot name="hot1" />
      </scene>
    
      <scene name="scene2">
        <view ath="20" atv="10" />
        <image url="img2.jgp" />
        <hotspot name="hot2" />
      </scene>
    </root>
    """
    

To parse this source you will create an etree:

    
    
    tree = etree.fromstring(source)
    

(For source coming from a file, use `etree.parse()` instead.)

Now you can browse through the parsed XML by accessing `tree` properly. My
favorite way of doing so is by navigating with XPaths (mastering these is out
of scope of your question):

    
    
    allViews = tree.xpath('//root/scene/view')
    for view in allViews:
      print view.attrib
    

This will print all XML attributes for each view tag found by the XPath:

    
    
    {'atv': '10', 'ath': '0'}
    {'atv': '10', 'ath': '20'}
    

Of course you can also access the other attributes of the view elements like
their embedded text (which is empty here of course) or their subelements
(children) (of course, in your example they also do not have children).

The wording of your question suggests that you might not have built up an
understanding of the fact that this `view` object is indeed "the entire view
tag". You can ask the `view` object for the tag it is made up of (`view`), for
its attributes (see above), its contents (`view.text`) and even its
subelements (`view.getchildren()`, but there are none).

You can convert the parsed XML structure back to an ASCII representation by
calling `etree.tostring(view)`; this will return a string like `'<view
ath="20" atv="10"/>\n '`. In most cases you will not do this.

You can also access the elements view the children of the elements:

    
    
    print tree.getchildren()[1].getchildren()[0].attrib
    

This will print the XML attributes of the 0th child (a `view`) of the first
child (a `scene`) of the `tree` element:

    
    
    {'atv': '10', 'ath': '20'}
    

