LXML树连接和属性

发布于 2025-01-17 19:28:46 字数 2742 浏览 2 评论 0原文

我有一个.dtsx文件,因此,我有多个具有连接的组件,因此我需要提取具有特殊连接的组件,但是我无法处理,例如:

<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>

我需要获取查询,其中< 相同级别,属性和连接代码为+/- like:

代码> ConnectionManagerId =“ package.connectionManagers [bi_sync]” ,但我无法处理,因为它们处于我使用的

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_name
                data["conn_dtsid"] = conn_dtsid
    if 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

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_name
                data["conn_dtsid"] = conn_dtsid
    if 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧瑾黎汐 2025-01-24 19:28:46

由于属性连接都是相同component的孩子,因此您可以使用XPath选择基于component基于连接,然后选择属性

因此,请尝试使用类似的内容,而不是在陈述中嵌套很多,

from lxml import etree

xml = """<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())

这会输出以下内容,以表明它选择了正确的属性 ...

<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>

有几个注释...

  • 我添加了一个root带有默认命名空间的元素,因此我的root变量将与您已经拥有的变量相似。
  • 我使用命名空间 kwarg,因此我可以在XPATH中使用前缀,而不是使用Clark符号。 (我认为更清洁。)

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 etree

xml = """<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.)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文