简体   繁体   English

从python中的ElementTree中删除空白的lxml元素

[英]Removing blank lxml element from ElementTree in python

I've been struggling with this for a couple of days now, and I figured I would ask here.我已经为此苦苦挣扎了几天,我想我会在这里问。

I am working on preparing an XML payload to POST to an Oracle endpoint that contains financials data.我正在准备 XML 有效负载以 POST 到包含财务数据的 Oracle 端点。 I've got most of the XML structured per Oracle specs, but I am struggling with one aspect of it.我已经按照 Oracle 规范构建了大部分 XML,但是我在其中的一个方面苦苦挣扎。 This is data that will feed the general ledger financial system and the xml structure is below (some elements have been omitted to cut down on the post.这是将提供给总账财务系统的数据,xml 结构如下(为了减少帖子,省略了一些元素。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://xmlns.oracle.com/apps/financials/generalLedger/journals/desktopEntry/journalImportService/types/" xmlns:jour="http://xmlns.oracle.com/apps/financials/generalLedger/journals/desktopEntry/journalImportService/">
  <soapenv:Header/>
  <soapenv:Body>
    <typ:importJournals>
      <typ:interfaceRows>
        <jour:BatchName>batch</jour:BatchName>
        <jour:AccountingPeriodName>Aug-20</jour:AccountingPeriodName>
        <jour:AccountingDate>2020-08-31</jour:AccountingDate>
        <jour:GlInterface>
          <jour:LedgerId>1234567890</jour:LedgerId>
          <jour:PeriodName>Aug-20</jour:PeriodName>
          <jour:AccountingDate>2020-08-31</jour:AccountingDate>
          <jour:Segment1>1</jour:Segment1>
          <jour:Segment2>1</jour:Segment2>
          <jour:Segment3>1</jour:Segment3>
          <jour:Segment4>1</jour:Segment4>
          <jour:Segment5>0</jour:Segment5>
          <jour:Segment6>0</jour:Segment6>
          <jour:CurrencyCode>USD</jour:CurrencyCode>
          <jour:EnteredCrAmount currencyCode="USD">10.0000</jour:EnteredCrAmount>
        </jour:GlInterface>
        <jour:GlInterface>
          <jour:LedgerId>1234567890</jour:LedgerId>
          <jour:PeriodName>Aug-20</jour:PeriodName>
          <jour:AccountingDate>2020-08-31</jour:AccountingDate>
          <jour:Segment1>2</jour:Segment1>
          <jour:Segment2>2</jour:Segment2>
          <jour:Segment3>2</jour:Segment3>
          <jour:Segment4>2</jour:Segment4>
          <jour:Segment5>0</jour:Segment5>
          <jour:Segment6>0</jour:Segment6>
          <jour:CurrencyCode>USD</jour:CurrencyCode>
          <jour:EnteredDrAmount currencyCode="USD">10.0000</jour:EnteredCrAmount>
        </jour:GlInterface>
      </typ:interfaceRows>
    </typ:importJournals>
  </soapenv:Body>
</soapenv:Envelope>

So if you look at the XML above, within the GlInterface tags, there are 2 per transaction (one is a debit and one is a credit, if you look at the Segments (account codes) they are different, and one GlInterface tag as a EnteredDrAmount tag, while the other has EnteredCrAmount tag.因此,如果您查看上面的 XML,在 GlInterface 标记中,每笔交易有 2 个(一个是借方,一个是贷方,如果您查看 Segments(帐户代码),它们是不同的,一个 GlInterface 标记作为EnteredDrAmount 标签,而另一个有 EnteredCrAmount 标签。

In the source data, either the Cr or Dr tag is null depending on if the line is a debit or credit, which comes in as "None" in python.在源数据中,Cr 或 Dr 标记为空,具体取决于行是借方还是贷方,在 python 中显示为“无”。

The way I got this to work is to call two calls to get data, one where Cr is not null and one where Dr is not null, and this process works fine, but in Python, I get an error "only one * allowed".我让它工作的方法是调用两个调用来获取数据,一个是 Cr 不为空,一个是 Dr 不为空,这个过程工作正常,但在 Python 中,我得到一个错误“只有一个 * 允许” . Code is below.代码如下。

    xmlOracle = x_Envelope(
        x_Header,
        x_Body(
            x_importJournals(
                x_interfaceRows(
                    x_h_BatchName(str(batch[0])),
                    x_h_AccountingPeriodName(str(batch[3])),
                    x_h_AccountingDate(str(batch[4])),
                    *[x_GlInterface(
                        x_d_LedgerId(str(adid[0])),
                        x_d_PeriodName(str(adid[1])),
                        x_d_AccountingDate(str(adid[2])),
                        x_d_Segment1(str(adid[5])),
                        x_d_Segment2(str(adid[6])),
                        x_d_Segment3(str(adid[7])),
                        x_d_Segment4(str(adid[8])),
                        x_d_Segment5(str(adid[9])),
                        x_d_Segment6(str(adid[10])),
                        x_d_CurrencyCode(str(adid[11])),
                        x_d_EnteredCrAmount(str(adid[14]), currencyCode=str(adid[11]))
                    ) for adid in CrAdidToProcess],
                    *[x_GlInterface(
                        x_d_LedgerId(str(adid[0])),
                        x_d_PeriodName(str(adid[1])),
                        x_d_AccountingDate(str(adid[2])),
                        x_d_Segment1(str(adid[5])),
                        x_d_Segment2(str(adid[6])),
                        x_d_Segment3(str(adid[7])),
                        x_d_Segment4(str(adid[8])),
                        x_d_Segment5(str(adid[9])),
                        x_d_Segment6(str(adid[10])),
                        x_d_CurrencyCode(str(adid[11])),
                        x_d_EnteredDrAmount(str(adid[14]), currencyCode=str(adid[11]))
                    ) for adid in DrAdidToProcess]
                )
            )
        )
    )

I've also tried making a single call to get the line details and then either removing or filtering out the tag (either Cr or Dr) if it's "None" but I had no luck with this.我也试过打一个电话来获取线路详细信息,然后删除或过滤掉标签(Cr 或 Dr),如果它是“无”,但我对此并不走运。

While the above process works, there is an error in my code, and I'd like to not have an error in my code.虽然上述过程有效,但我的代码中存在错误,我希望我的代码中没有错误。

Thank you all.谢谢你们。

After further testing, I believe I figured out the solution to this.经过进一步测试,我相信我找到了解决方案。 I believe I was trying to remove an element from ElementTree object and it was not having any of that.我相信我试图从 ElementTree 对象中删除一个元素,但它没有任何元素。 When I passed an element to the remove method/function, it finally worked.当我将一个元素传递给 remove 方法/函数时,它终于起作用了。

Here is code for the function to remove the "None" entries.这是删除“无”条目的函数的代码。

def removeCrDrEmptyElements(element):
    for removeElement in element.xpath('/soapenv:Envelope/soapenv:Body/typ:importJournals/typ:interfaceRows/jour:GlInterface/jour:EnteredCrAmount',
                                         namespaces = { 'soapenv' : 'http://schemas.xmlsoap.org/soap/envelope/',
                                                        'typ' : 'http://xmlns.oracle.com/apps/financials/generalLedger/journals/desktopEntry/journalImportService/types/',
                                                        'jour' : 'http://xmlns.oracle.com/apps/financials/generalLedger/journals/desktopEntry/journalImportService/'
                                                      }):
        if removeElement.text == 'None':
            removeElement.getparent().remove(removeElement)

    for removeElement in element.xpath('/soapenv:Envelope/soapenv:Body/typ:importJournals/typ:interfaceRows/jour:GlInterface/jour:EnteredDrAmount',
                                         namespaces = { 'soapenv' : 'http://schemas.xmlsoap.org/soap/envelope/',
                                                        'typ' : 'http://xmlns.oracle.com/apps/financials/generalLedger/journals/desktopEntry/journalImportService/types/',
                                                        'jour' : 'http://xmlns.oracle.com/apps/financials/generalLedger/journals/desktopEntry/journalImportService/'
                                                      }):
        if removeElement.text == 'None':
            removeElement.getparent().remove(removeElement)

    return element

Obviously this can be better rewritten (which I will do) but I only want to check two elements within the GlInterface tag, the EnteredCrAmount and EnteredDrAmount and remove those elements if the text is None.显然,这可以更好地重写(我会这样做),但我只想检查 GlInterface 标记中的两个元素,即 EnteredCrAmount 和 EnteredDrAmount,如果文本为 None,则删除这些元素。

Then you can call the function by using the code below to return an element type with the removed Nulls/Nones然后,您可以使用以下代码调用该函数,以返回带有已删除 Nulls/Nones 的元素类型

xmlWithoutNull = removeCrDrEmptyElements(xmlElement)

Output before running function results:运行函数结果前的输出:

        <jour:GlInterface>
          # omitted elements
          <jour:EnteredCrAmount currencyCode="USD">1.000000</jour:EnteredCrAmount>
          <jour:EnteredDrAmount currencyCode="USD">None</jour:EnteredDrAmount>
          # omitted elements
        </jour:GlInterface>
        <jour:GlInterface>
          # omitted elements
          <jour:EnteredCrAmount currencyCode="USD">None</jour:EnteredCrAmount>
          <jour:EnteredDrAmount currencyCode="USD">1.000000</jour:EnteredDrAmount>
          # omitted elements
        </jour:GlInterface>

Output after running function results:运行函数结果后输出:

        <jour:GlInterface>
          # omitted elements
          <jour:EnteredCrAmount currencyCode="USD">1.000000</jour:EnteredCrAmount>
          # omitted elements
        </jour:GlInterface>
        <jour:GlInterface>
          # omitted elements
          <jour:EnteredDrAmount currencyCode="USD">1.000000</jour:EnteredDrAmount>
          # omitted elements
        </jour:GlInterface>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM