I'm trying to link two existing Python ElementTree objects together.
import xml.etree.ElementTree as ET
root = ET.Element('Hello')
root2 = ET.Element('World')
node = ET.SubElement(root2, 'country')
node.text = 'Belgium'
When printed
print(ET.tostring(root))
print(ET.tostring(root2))
I get
b'<Hello />'
b'<World><country>Belgium</country></World>'
How do I add root2 to root, to get the result? `
print(ET.tostring(root))
b'<Hello><World><country>Belgium</country></World></Hello>'
How about
import xml.etree.ElementTree as ET
hello = ET.Element('Hello')
world = ET.Element('World')
hello.insert(0,world)
country = ET.SubElement(world,'Country')
country.text = 'Belgium'
print(ET.tostring(hello))
Output
b'<Hello><World><Country>Belgium</Country></World></Hello>'
It seems, that I can use the same syntax as in lists
root.append(root2)
print(ET.tostring(root))
b'<Hello><World><country>Belgium</country></World></Hello>'
Related
I have an XML file like the following:
<AreaModel>
...
<RecipePhase>
<UniqueName>PHASE1</UniqueName>
...
<NumberOfParameterTags>7</NumberOfParameterTags>
...
<DefaultRecipeParameter>
<Name>PARAM1</Name>
----
</DefaultRecipeParameter>
<DefaultRecipeParameter>
<Name>PARAM2</Name>
----
</DefaultRecipeParameter>
<DefaultRecipeParameter>
<Name>PARAM3</Name>
----
</DefaultRecipeParameter>
</RecipePhase>
<RecipePhase>
....
</RecipePhase>
</AreaModel>
I would like to read this file in sequential order and generate different list. One for the texts of UniqueName TAGs and a list of lists containing for each list the set of texts for tag Name under each RecipePhase element.
For example, I might have 10 RecipePhase elements, each one with TAG UniqueName and each one containing a different set of children with tag DefaultRecipeParameter.
How can I take into account when I enter into RecipePhase and when I go out of the element during parsing?
I am trying ElementTree but I am not able to find a solution.
cheers,
m
You can use xml python module:
See my example:
from xml.dom import minidom as dom
import urllib2
def fetchPage(url):
a = urllib2.urlopen(url)
return ''.join(a.readlines())
def extract(page):
a = dom.parseString(page)
item = a.getElementsByTagName('Rate')
for i in item:
if i.hasChildNodes() == True:
print i.getAttribute('currency')+"-"+ i.firstChild.nodeValue
if __name__=='__main__':
page = fetchPage("http://www.bnro.ro/nbrfxrates.xml")
extract(page)
I solved partially my problem with the following code:
import xml.etree.ElementTree as ET
tree = ET.parse('control_strategies.axml')
root = tree.getroot()
phases=[]
for recipephase in root.findall('./RecipePhase/UniqueName'):
phases.append(recipephase.text)
n_elem = len(phases)
param=[[] for _ in range(n_elem)]
i = 0
for recipephase in root.findall('./RecipePhase'):
for defparam in recipephase.findall('./DefaultRecipeParameter'):
for paramname in defparam.findall('./Name'):
param[i].append(paramname.text)
i = i + 1
I'm trying to parse and read an xml with xml.etree.ElementTree (I can't move to lxml) but I've been unable to.
XML: https://pastebin.com/yJqAW0L0
<GetResponse xmlns="http://mywebsite.com/myservice/">
<AutoScalingGroup>
<AutoScalingGroupName>foo</AutoScalingGroupName>
<AttributeValuePair>
<Attribute>owner</Attribute>
<Value>bob</Value>
</AttributeValuePair>
</AutoScalingGroup>
</GetResponse>
I've tried doing
import xml.etree.ElementTree as ET
ET.register_namespace('', "http://mywebsite.com/myservice/")
NSMAP = {'service':'http://mywebsite.com/myservice/'}
tree = ET.fromstring(page) # This is where i grab the xml from
autoscalingGroups = tree.findall('.//service:AutoScalingGroup', namespaces = NSMAP)
for asg in autoscalingGroups:
name = asg.findtext('.//service:AutoScalingGroupName', namespaces = NSMAP, default = "Default asg name")
print "asg name: " + str(name)
This doesn't return anything and I'm struggling to find why.
1) how do i get 'foo'?
2) how do i get 'bob'?
Am i using the wrong XML xpath?
I have follwing xml file:
<root>
<nodeA>
<childrens_A>
</nodeA>
<nodeB>
<childrens_B>
</nodeB>
<nodeA>
<childrens_A>
</nodeA>
<nodeB>
<childrens_B>
</nodeB>
</root>
I want get something like
<root>
<nodeA>
<childrens_A>
<childrens_B>
</nodeA>
<nodeA>
<childrens_A>
<childrens_B>
</nodeA>
</root>
Numbers of nodes A and B equal.
I can import only from standard python library. I cannot import lxml because access restriction. So i want be limited from xml.etree import ElementTree as et
My code is:
from xml.etree import ElementTree as et
tree = et.parse(path_in)
root = tree.getroot()
for child in root.gethcildren()
if child.tag == "nodeA"
#insert children of nodeB in nodeA
tr.write(path_out)
Thanks in advance!
Looks like i find solution:
from xml.etree import ElementTree as et
tr = et.parse(path_in)
root = tr.getroot()
for child in root.getchildren():
if child.tag == 'nodeB':
sub = child.getchildren()
i = root.getchildren().index(child)
root.getchildren()[i - 1].extend(sub)
tr.write(path_out)
Hope once this answer can help to somebody.
I have the following structure in an XML file:
<current>
<city id="2510170" name="Triana">
<coord lon="-6.02" lat="37.38"/>
<country>ES</country>
<sun rise="2016-04-04T06:04:05" set="2016-04-04T18:50:07"/>
</city>
<temperature value="290.92" min="288.15" max="296.15" unit="kelvin"/>
<humidity value="93" unit="%"/>
<pressure value="1009" unit="hPa"/>
<wind>
<speed value="8.2" name="Fresh Breeze"/>
<gusts/>
<direction value="230" code="SW" name="Southwest"/>
</wind>
<clouds value="90" name="overcast clouds"/>
<visibility/>
<precipitation mode="no"/>
<weather number="501" value="moderate rain" icon="10d"/>
<lastupdate value="2016-04-04T10:05:00"/>
</current>
The question is how to extract the temperature ( #value ) using XPATH of Python ?. That is, extract from "290.2" of the following line:
<temperature value="290.92" min="288.15" max="296.15" unit="kelvin"/>
Assuming that root reffers to <current> node
from lxml import etree
xml_file = 'test.xml'
with open(xml_file) as xml:
root = etree.XML(xml.read())
temperature_value = root.xpath('./temperature/#value')[0]
I would simply do
import xml.etree.ElementTree as ET
root = ET.parse('path_to_your_xml_file')
temperature = root.find('.//temperature')
Now temperature.attrib is a dictionary with all of the info
print temperature.attrib['value'] # 290.92
print temperature.attrib['min'] # 288.15
print temperature.attrib['max'] # 296.15
print temperature.attrib['unit'] # kelvin
from xml.etree import cElementTree as ET
tree = ET.parse("test.xml")
root = tree.getroot()
for temp in root.findall('temperature'):
print(temp.get("value"))
I am new to Python. Now I have to replace a number of values in an XML file with Python. The example snippet of XML is:
<gmd:extent>
<gmd:EX_Extent>
<gmd:description gco:nilReason="missing">
<gco:CharacterString />
</gmd:description>
<gmd:geographicElement>
<gmd:EX_GeographicBoundingBox>
<gmd:westBoundLongitude>
<gco:Decimal>112.907</gco:Decimal>
</gmd:westBoundLongitude>
<gmd:eastBoundLongitude>
<gco:Decimal>158.96</gco:Decimal>
</gmd:eastBoundLongitude>
<gmd:southBoundLatitude>
<gco:Decimal>-54.7539</gco:Decimal>
</gmd:southBoundLatitude>
<gmd:northBoundLatitude>
<gco:Decimal>-10.1357</gco:Decimal>
</gmd:northBoundLatitude>
</gmd:EX_GeographicBoundingBox>
</gmd:geographicElement>
</gmd:EX_Extent>
</gmd:extent>
What I want to do is to replace those decimal values, i.e. 112.907, with a specified value.
<gmd:extent>
<gmd:EX_Extent>
<gmd:description gco:nilReason="missing">
<gco:CharacterString />
</gmd:description>
<gmd:geographicElement>
<gmd:EX_GeographicBoundingBox>
<gmd:westBoundLongitude>
<gco:Decimal>new value</gco:Decimal>
</gmd:westBoundLongitude>
<gmd:eastBoundLongitude>
<gco:Decimal>new value</gco:Decimal>
</gmd:eastBoundLongitude>
<gmd:southBoundLatitude>
<gco:Decimal>new value</gco:Decimal>
</gmd:southBoundLatitude>
<gmd:northBoundLatitude>
<gco:Decimal>new value</gco:Decimal>
</gmd:northBoundLatitude>
</gmd:EX_GeographicBoundingBox>
</gmd:geographicElement>
</gmd:EX_Extent>
</gmd:extent>
I tried with a few methods but none of them worked with my assumption that the difficulty is with the namespace prefix gmd and gco.
Please help me out. Thanks in advance!
Cheers, Alex
I couldn't get lxml to process your xml without adding fake namespace declarations at the top so here is how your input looked
<gmd:extent xmlns:gmd="urn:x:y:z:1" xmlns:gco="urn:x:y:z:1">
<gmd:EX_Extent>
<gmd:description gco:nilReason="missing">
<gco:CharacterString />
</gmd:description>
<gmd:geographicElement>
<gmd:EX_GeographicBoundingBox>
<gmd:westBoundLongitude>
<gco:Decimal>112.907</gco:Decimal>
</gmd:westBoundLongitude>
<gmd:eastBoundLongitude>
<gco:Decimal>158.96</gco:Decimal>
</gmd:eastBoundLongitude>
<gmd:southBoundLatitude>
<gco:Decimal>-54.7539</gco:Decimal>
</gmd:southBoundLatitude>
<gmd:northBoundLatitude>
<gco:Decimal>-10.1357</gco:Decimal>
</gmd:northBoundLatitude>
</gmd:EX_GeographicBoundingBox>
</gmd:geographicElement>
</gmd:EX_Extent>
</gmd:extent>
I assumed you have two lists one for the current values and one for the new ones like this
old = [112.907, 158.96, -54.7539, -10.1357]
new = [1,2,3,4]
d = dict(zip(old,new))
Here is the full code
#!/usr/bin/env python
import sys
from lxml import etree
def process(fname):
f = open(fname)
tree = etree.parse(f)
root = tree.getroot()
old = [112.907, 158.96, -54.7539, -10.1357]
new = [1,2,3,4]
d = dict(zip(old,new))
nodes = root.findall('.//gco:Decimal', root.nsmap)
for node in nodes:
node.text = str(d[float(node.text)])
f.close()
return etree.tostring(root, pretty_print=True)
def main():
fname = sys.argv[1]
text = process(fname)
outfile = open('out.xml', 'w+')
outfile.write(text)
outfile.close()
if __name__ == '__main__':
main()
and here is how the output looked like
<gmd:extent xmlns:gmd="urn:x:y:z:1" xmlns:gco="urn:x:y:z:1">
<gmd:EX_Extent>
<gmd:description gco:nilReason="missing">
<gco:CharacterString/>
</gmd:description>
<gmd:geographicElement>
<gmd:EX_GeographicBoundingBox>
<gmd:westBoundLongitude>
<gco:Decimal>1</gco:Decimal>
</gmd:westBoundLongitude>
<gmd:eastBoundLongitude>
<gco:Decimal>2</gco:Decimal>
</gmd:eastBoundLongitude>
<gmd:southBoundLatitude>
<gco:Decimal>3</gco:Decimal>
</gmd:southBoundLatitude>
<gmd:northBoundLatitude>
<gco:Decimal>4</gco:Decimal>
</gmd:northBoundLatitude>
</gmd:EX_GeographicBoundingBox>
</gmd:geographicElement>
</gmd:EX_Extent>
</gmd:extent>