I have a .dtsx
file so, I have multiple components with connections, so I need to extract component that have especific connection, but I can not handle that, example:
<components><component refId="Component_1 Name" componentClassID="componentClassID" contactInfo="contactInfo" description="description" name="name" usesDispositions="true" version="6"><properties><property dataType="System.String" description="description" expressionType="Notify" name="SqlCommandParam" UITypeEditor="UITypeEditor">QUERY THAT i NEED TO GET</property></properties><connections><connection refId="Name" connectionManagerID="Package.ConnectionManagers[BI_SYNC]" connectionManagerRefId="Package.ConnectionManagers[BI_SYNC]" description="description" name="OleDbConnection" /></connections></component><component refId="Component_2 Name" componentClassID="componentClassID" contactInfo="contactInfo" description="description" name="PartnerService" usesDispositions="true" version="6"><properties><property dataType="System.String" description="description" expressionType="Notify" name="SqlCommandParam" UITypeEditor="UITypeEditor">QUERY THAT I DONT NEED TO GET</property></properties><connections><connection refId="Name" connectionManagerID="Package.ConnectionManagers[BI_STG]" connectionManagerRefId="Package.ConnectionManagers[BI_STG]" description="description" name="OleDbConnection" /></connections></component>
</components>
I need to get the query where connectionManagerID="Package.ConnectionManagers[BI_SYNC]"
But I cannot handle that because they are in the same level, properties and connections
Code that I am using is +/- like:
for cnt, element in enumerate(root.xpath(".//*")):if cnt == 0:file = root.attrib["{www.microsoft.com/SqlServer/Dts}ObjectName"]data["file_name"] = file + ".dtsx"if element.tag == con_tag:if element.attrib.get("{www.microsoft.com/SqlServer/Dts}ObjectName"):if element.attrib.get("{www.microsoft.com/SqlServer/Dts}ObjectName", None) == "BI_SYNC":conn_name = element.attrib.get("{www.microsoft.com/SqlServer/Dts}ObjectName", None)conn_dtsid = element.attrib.get("{www.microsoft.com/SqlServer/Dts}DTSID", None)data["conn_name"] = conn_namedata["conn_dtsid"] = conn_dtsidif element.tag == exec_tag:for cnt_0, element_0 in enumerate(element):if element_0.tag == execs_tag:for cnt_1, element_1 in enumerate(element_0): # Get package name
Since properties
and connections
are both children of the same component
, you can use xpath to select the component
based on the connection
, then select the property
.
So instead of a lot of nested if and for statements, try something like...
from lxml import etreexml = """<root xmlns="www.microsoft.com/SqlServer/Dts"><components><component refId="Component_1 Name" componentClassID="componentClassID" contactInfo="contactInfo" description="description" name="name" usesDispositions="true" version="6"><properties><property dataType="System.String" description="description" expressionType="Notify" name="SqlCommandParam" UITypeEditor="UITypeEditor">QUERY THAT i NEED TO GET</property></properties><connections><connection refId="Name" connectionManagerID="Package.ConnectionManagers[BI_SYNC]" connectionManagerRefId="Package.ConnectionManagers[BI_SYNC]" description="description" name="OleDbConnection"/></connections></component><component refId="Component_2 Name" componentClassID="componentClassID" contactInfo="contactInfo" description="description" name="PartnerService" usesDispositions="true" version="6"><properties><property dataType="System.String" description="description" expressionType="Notify" name="SqlCommandParam" UITypeEditor="UITypeEditor">QUERY THAT I DONT NEED TO GET</property></properties><connections><connection refId="Name" connectionManagerID="Package.ConnectionManagers[BI_STG]" connectionManagerRefId="Package.ConnectionManagers[BI_STG]" description="description" name="OleDbConnection"/></connections></component></components>
</root>
"""root = etree.fromstring(xml)ns = {"dts": "www.microsoft.com/SqlServer/Dts"}for property_elem in root.xpath(".//dts:component[dts:connections/dts:connection[@connectionManagerID='Package.ConnectionManagers[BI_SYNC]']]/dts:properties/dts:property", namespaces=ns):print(etree.tostring(property_elem).decode())
This outputs the following to show that it selects the correct property
...
<property xmlns="www.microsoft.com/SqlServer/Dts" dataType="System.String" description="description" expressionType="Notify" name="SqlCommandParam" UITypeEditor="UITypeEditor">QUERY THAT i NEED TO GET</property>
A couple of notes...
- I added a
root
element with the default namespace so my root
variable would work similar to what you already have.
- I use the
namespaces
kwarg so I could use a prefix in my xpath instead of using Clark notation. (Cleaner in my opinion.)