python lxml etree parsing an fvdl file - python

The file contains the following lines.
<?xml version="1.0" encoding="UTF-8"?>
<FVDL xmlns="xmlns://www.fortifysoftware.com/schema/fvdl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.9" xsi:type="FVDL">`
<CreatedTS date="2013-08-06" time="11:8:48" />`
I am trying to read the version tag in FVDL.I am using lxml etree and my code snippet is
from lxml import etree
with open(os.path.join(analysis,"merged-results.fvdl") ,"r") as file_handle:
context = etree.parse(file_handle)
ver = context.xpath('//FVDL')
print ver
This had worked before in parsing a standard xml file. However it is failing for the above mentioned file .(ver is an empty list at the end of execution)

Alternative to #falsetru's answer
(By "trying to read the version tag", I understand "the version attribute" (which may not be what you want))
Explicitly register fvdl namespace, under the "fvdl" prefix:
ver = context.xpath('//fvdl:FVDL/#version',
namespaces={"fvdl": "xmlns://www.fortifysoftware.com/schema/fvdl"})
Or, riskier, if somehow you know you want the version attribute from the root node
ver = context.xpath('/*/#version')
Both give ['1.9']

context = etree.parse(file_handle)
ver = context.getroot()
print ver.attrib['version']
output:'1.9'

Use [local-name()=...]:
ver = context.xpath('//*[local-name()="FVDL"]')

Related

Removing ":" from namespace in a XML file parsing

I am trying to modify XML file using xml.etree.ElementTree on Python 2.6.6 (due to restrictions) and facing ns0 issue. I looked at this issue and used ET._namespace_map[uri] = prefix as suggested which removed ns0 but the element tags still has the : value. How do we remove it or does it impact the validity of the XML file when we use if for further processing?
Example:
<?xml version="1.0" encoding="UTF-8" ?>
<Seed xmlns="http://www.example.com">
<TagA>
<TagB>B</TagB>
<TagC>c</TagC>
</TagA>
</Seed>
Script
import xml.etree.ElementTree as ET
tree = ET.parse('sample.xml')
root = tree.getroot()
try:
ET.register_namespace("","http://example.com")
except AttributeError:
def register_namespace(prefix, uri):
ET._namespace_map[uri] = prefix
register_namespace("","http://www.example.com")
tree.write('sample.xml')
Note: I could not use lxml or other xml.etree that is supported only from 2.7 version.

How to write an xml file using libxml2 in python?

I am attempting to write an xml file in python3 using libxml2. I cannot find any relevant documentation regarding python about writing files with libxml. When I attempt to write an xml file parsed with libxml2 I get the error:
xmlDoc has no attribute write
Anyone here done this before? I can get it to work in Etree just fine but Etree will not respect the attribute order that I need.
You can use saveFile() or saveFileEnc(). Example:
import libxml2
XML = """
<root a="1" b="2">XYZ</root>
"""
doc = libxml2.parseDoc(XML)
doc.saveFile("test.xml")
doc.saveFileEnc("test2.xml", "UTF-8")
I could not find any good documentation for the Python API. Here is the corresponding C documentation: http://xmlsoft.org/html/libxml-tree.html#xmlSaveFile.
import libxml2
DOC = """<?xml version="1.0" encoding="UTF-8"?>
<verse>
<attribution>Christopher Okibgo</attribution>
<line>For he was a shrub among the poplars,</line>
<line>Needing more roots</line>
<line>More sap to grow to sunlight,</line>
<line>Thirsting for sunlight</line>
</verse>
"""
doc = libxml2.parseDoc(DOC)
root = doc.children
print root

Python xml.etree issue

I'm trying to build a script in python 3 using xml.etree which accepts version as a parameter , parses xml and replace the version in the xml tags + values from the tree to the root and his children.
I am at the point where i can change the default value in the root but i am struggling with changing the version to childs and grandchilds - CurrentVersion, Template and Base.
Here is my code and XML:
code-
import sys
from xml.etree import ElementTree as et
version = sys.argv[1]
parse = et.parse("WebApp2.config")
root = parse.getroot()
def changeVersion(version):
ourVersion = root.find('OurVersion')
root.set("default", version)
print(et.tostring(root))
parse.write("WebApp2.config", xml_declaration=True)
if __name__ == "__main__":
changeVersion(version)
XML-
<?xml version="1.0"?>
<OurVersion default="1.0.0.3">
<CurrentVersion bitSupport="true" deviceDetectionSupport="true"
version="1.0.0.3">
<Template>D:\Some\Path\Software\1.0.0.3\webApp\index.webapp</Template>
<BasePath>resources/1.0.0.3/webApp/</BasePath>
</CurrentVersion>
</OurVersion>
I've tried to add something like the below, but im getting issue that "no set attribue to currentVersion" -
ourVersion = root.find('OurVersion')
ourVersion.set('default`, version)
currentVersion = ourVersion.find('CurrentVersion')
currentVersion.set('version', version)
Appreciate your help on this matter ;)
Your first script works because with root.set("default", version) you are using root to refer to the attribute default that you want to modify.
In fact ourVersion = root.find('OurVersion') returns nothing (None) because
OurVersion is your root and then ourVersion.find('CurrentVersion') cannot return what you expect.
Try this instead :
currentVersion = root.find('CurrentVersion')
currentVersion.set('version', version)

python elementree blank output

I am parsing an XML output from VCloud, however I am not able to reach to the values
<?xml version="1.0" encoding="UTF-8"?>
<SupportedVersions xmlns="http://www.vmware.com/vcloud/versions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/versions http://10.10.6.12/api/versions/schema/versions.xsd">
<VersionInfo>
<Version>1.5</Version>
<LoginUrl>https://api.vcd.portal.skyscapecloud.com/api/sessions</LoginUrl>
<MediaTypeMapping>
<MediaType>application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml</MediaType>
<ComplexTypeName>InstantiateVAppTemplateParamsType</ComplexTypeName>
<SchemaLocation>http://api.vcd.portal.skyscapecloud.com/api/v1.5/schema/master.xsd</SchemaLocation>
</MediaTypeMapping>
<MediaTypeMapping>
<MediaType>application/vnd.vmware.admin.vmwProviderVdcReferences+xml</MediaType>
<ComplexTypeName>VMWProviderVdcReferencesType</ComplexTypeName>
<SchemaLocation>http://api.vcd.portal.skyscapecloud.com/api/v1.5/schema/vmwextensions.xsd</SchemaLocation>
</MediaTypeMapping>
<MediaTypeMapping>
<MediaType>application/vnd.vmware.vcloud.customizationSection+xml</MediaType>
<ComplexTypeName>CustomizationSectionType</ComplexTypeName>
<SchemaLocation>http://api.vcd.portal.skyscapecloud.com/api/v1.5/schema/master.xsd</SchemaLocation>
</MediaTypeMapping>
this is what I have been using
import xml.etree.ElementTree as ET
data = ET.fromstring(content)
versioninfo = data.findall("VersionInfo/Version")
print len(versioninfo)
print versioninfo.text
however this gives a blank output...any suggestions?
Try this:
import xml.etree.ElementTree as ET
data = ET.fromstring(content)
versioninfo = data.find(
"ns:VersionInfo/ns:Version",
namespaces={'ns':'http://www.vmware.com/vcloud/versions'})
print versioninfo.text
Use .find(), not .findall() to return a single element
Your XML uses namespaces. The full path to your desired object is: '{http://www.vmware.com/vcloud/versions}VersionInfo/{http://www.vmware.com/vcloud/versions}Version' By passing in the namespaces parameter, you are able to use the shortcut syntax: ns:VersionInfo/ns:Version.

python lxml with py2exe

I have Generated an XML with dom and i want to use lxml to pretty print the xml.
this is my code for pretty print the xml
def prettify_xml(xml_str):
import lxml.etree as etree
root = etree.fromstring(xml_str)
xml_str = etree.tostring(root, pretty_print=True)
return xml_str
my output should be an xml formatted string.
I got this code from some post in stactoverflow. This works flawlessly when i am compiling wit python itself. But when i convert my project to a binary created from py2exe (my binary is windows service with a namedpipe).I had two problems:
My service was not starting , i solved this by adding lxml.etree in includes option in py2exe function. then on my service started properly.
when xml generation in called here, is the error which I am seeing in my log
'module' object has no attribute 'fromstring'
where do i rectify this error ? And Is my first problem's solution correct ?
my xml generation Code :
from xml.etree import ElementTree
from xml.dom import minidom
from xml.etree.ElementTree import Element, SubElement, tostring, XML
import lxml.etree
def prettify_xml(xml_str):
root = lxml.etree.fromstring(xml_str)
xml_str = lxml.etree.tostring(root, pretty_print=True)
return xml_str
def dll_xml(status):
try:
xml_declaration = '<?xml version="1.0" standalone="no" ?>'
rootTagName='response'
root = Element(rootTagName)
root.set('id' , 'rp001')
parent = SubElement(root, 'command', opcode ='-ac')
# Create children
chdtag1Name = 'mode'
chdtag1Value = 'repreport'
chdtag2Name='status'
chdtag2Value = status
fullchildtag1 = ''+chdtag1Name+' value = "'+chdtag1Value+'"'
fullchildtag2=''+chdtag2Name+' value="'+chdtag2Value+'"'
children = XML('''<root><'''+fullchildtag1+''' /><'''+fullchildtag2+'''/></root> ''')
# Add parent
parent.extend(children)
dll_xml_doc = xml_declaration + tostring(root)
dll_xml_doc = prettify_xml(dll_xml_doc)
return dll_xml_doc
except Exception , error:
log.error("xml_generation_failed : %s" % error)
Try to use PyInstaller instead py2exe. I converted your program to binary .exe with no problem just by running python pyinstaller.py YourPath\xml_a.py.

Categories