簡體   English   中英

Python Beautiful Soup XML條件查詢(混合標簽和屬性)解析

[英]Python Beautiful Soup XML Conditional Query (mixed tags and attributes) Parsing

我有兩個版本的 XML 文件需要從中提取內容。 兩者都具有以下兩種不同格式的相同信息(不僅是不同的標簽,而且是不同的結構):

  1. 第一個在<activeelementSubstance></activeelementSubstance><inactiveelementSubstance></inactiveelementSubstance>之間定義了活動和非活動元素
  2. 第二個定義了活動和非活動元素: <element classCode="IACT"></element classCode="IACT"><element classCode="ACTIM"></element classCode="ACTIM">

如何解決這兩種情況以提取 Inactive 和 Active Elements ? (有幾個標簽有同義詞的例子,但我沒有看到任何實際結構與這種情況不同的地方)

我想出了以下代碼(不是很干凈)從第二種情況(提取元素及其代碼)中提取:

activeElements = soup.findAll('Element', attrs={'classCode': 'ACTIM'})
for i in activeElements:
    aiName = i.find('name')
    aiCode = str(i.find('code'))
    print(aiName.text)
    print( re.findall(r'"(.*?)"', aiCode)[0] )


print('\nInactive Elements\n')

inactiveElements = soup.findAll('Element', attrs={'classCode': 'IACT'})
for i in inactiveElements:
    aiName = i.find('name')
    print(aiName.text)
    aiCode = i.find('code')['code']
    print(aiCode)

XML 文件的示例如下:

第一種類型(格式為<element classCode="IACT"></element classCode="IACT"><element classCode="ACTIM"></element classCode="ACTIM"> ):

<?xml version="1.0" encoding="UTF-8"?>
<document>
<manufacturedProduct>
<element classCode="IACT">
<elementSubstance>
<code code="36SFW2JZ" codeSystem="33590coding"/>
<name>HYPROMELLOSE 2910 (15 MPA.S)</name>
</elementSubstance>
</element>
<element classCode="IACT">
<elementSubstance>
<code code="70097M6I" codeSystem="33590coding"/>
<name>MAGNESIUM STEARATE</name>
</elementSubstance>
</element>
<elementSubstance>
<code code="XHX3C3X6" codeSystem="33590coding"/>
<name>TRIACETIN</name>
</elementSubstance>
</element>
<element classCode="ACTIM">
<quantity>
<numerator unit="mg" value="250"/>
<denominator unit="1" value="1"/>
</quantity>
<elementSubstance>
<code code="JTE4MNN1" codeSystem="33590coding"/>
<name>AZITHROMYCIN MONOHYDRATE</name>
</elementSubstance>
</element>
</manufacturedProduct>
</document>

第二種類型(格式為<activeelementSubstance></activeelementSubstance><inactiveelementSubstance></inactiveelementSubstance> ):

<?xml version="1.0" encoding="UTF-8"?>
<document>
<manufacturedProduct>
<activeelementSubstance>
<code code="VB0R961H" codeSystem="33590coding" codeSystemName="USDA" />
<name>Prednisone</name>
</activeelementSubstance>
</activeelement>
<inactiveelement>
<inactiveelementSubstance>
<code code="776XM704" codeSystem="33590coding" codeSystemName="USDA" />
<name>calcium stearate</name>
</inactiveelementSubstance>
</inactiveelement>
<inactiveelement>
<inactiveelementSubstance>
<name>corn starch</name>
</inactiveelementSubstance>
</inactiveelement>
</manufacturedProduct>
</document>

XML 文件嵌套很深(這也是我使用 Beautiful soup 的部分原因),我嘗試清理並提取它們的相關部分。

您可以在 CSS 選擇器列表中使用 CSS OR 語法,而不是添加條件邏輯來確定分配提取結果的位置。 下面可以通過重構來減少嵌套,例如將某些部分移動到它們自己的函數中,但它提供了一個起點。

from bs4 import BeautifulSoup as bs

type_1 = '''
<?xml version="1.0" encoding="UTF-8"?>
<document>
<manufacturedProduct>
<element classCode="IACT">
<elementSubstance>
<code code="36SFW2JZ" codeSystem="33590coding"/>
<name>HYPROMELLOSE 2910 (15 MPA.S)</name>
</elementSubstance>
</element>
<element classCode="IACT">
<elementSubstance>
<code code="70097M6I" codeSystem="33590coding"/>
<name>MAGNESIUM STEARATE</name>
</elementSubstance>
</element>
<elementSubstance>
<code code="XHX3C3X6" codeSystem="33590coding"/>
<name>TRIACETIN</name>
</elementSubstance>
</element>
<element classCode="ACTIM">
<quantity>
<numerator unit="mg" value="250"/>
<denominator unit="1" value="1"/>
</quantity>
<elementSubstance>
<code code="JTE4MNN1" codeSystem="33590coding"/>
<name>AZITHROMYCIN MONOHYDRATE</name>
</elementSubstance>
</element>
</manufacturedProduct>
</document>'''

type_2 = '''
<?xml version="1.0" encoding="UTF-8"?>
<document>
<manufacturedProduct>
<activeelementSubstance>
<code code="VB0R961H" codeSystem="33590coding" codeSystemName="USDA" />
<name>Prednisone</name>
</activeelementSubstance>
</activeelement>
<inactiveelement>
<inactiveelementSubstance>
<code code="776XM704" codeSystem="33590coding" codeSystemName="USDA" />
<name>calcium stearate</name>
</inactiveelementSubstance>
</inactiveelement>
<inactiveelement>
<inactiveelementSubstance>
<name>corn starch</name>
</inactiveelementSubstance>
</inactiveelement>
</manufacturedProduct>
</document>'''


results = {'active': [], 'inactive': []}

for doc in [type_1, type_2]:
    
    soup = bs(doc, 'lxml')
    
    for i in soup.select('[classcode=IACT], [classcode=ACTIM], activeelement, inactiveelement'):

        if i.get('classcode') == 'IACT' or i.name == 'inactiveelement':
            try:
                d = {i.select_one('name').text:i.select_one('code')['code']}
            except:
                d = {i.select_one('name').text:'missing'}
            results['inactive'].append(d)
        else:
            results['active'].append({i.select_one('name').text:i.select_one('code')['code']})
            
print(results)

您可以將 CSS 選擇器與,一起使用。 例如:

from bs4 import BeautifulSoup

xml_doc1 = ...version 1 of the xml document...
xml_doc2 = ...version 2 of the xml document...


soup = BeautifulSoup(xml_doc1 + xml_doc2, "html.parser")

elem = soup.select(
    'element[classCode="IACT"], element[classCode="ACTIM"], activeelementSubstance, inactiveelementSubstance'
)

for e in elem:
    code = c["code"] if (c := e.code) else "-"
    name = n.text if (n := e.find("name")) else "-"

    print(code, name)

印刷:

36SFW2JZ HYPROMELLOSE 2910 (15 MPA.S)
70097M6I MAGNESIUM STEARATE
JTE4MNN1 AZITHROMYCIN MONOHYDRATE
VB0R961H Prednisone
776XM704 calcium stearate
- corn starch

或分為活動和非活動:

print("Active Elements")

elem = soup.select('element[classCode="ACTIM"], activeelementSubstance')

for e in elem:
    code = c["code"] if (c := e.code) else "-"
    name = n.text if (n := e.find("name")) else "-"

    print(code, name)


print("\nInactive Elements")

elem = soup.select('element[classCode="IACT"], inactiveelementSubstance')

for e in elem:
    code = c["code"] if (c := e.code) else "-"
    name = n.text if (n := e.find("name")) else "-"

    print(code, name)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM