У меня есть документ XML, который я анализирую для получения нескольких данных getElementsByTagName - PullRequest
0 голосов
/ 31 марта 2020

Я работаю над проектом для компании, в которой я работаю. У них есть программа, которая генерирует файл XML, и она хотела бы извлечь и отформатировать указанные имена тегов c как форматированный вывод. Чтобы выполнить sh, я обратился к Python и в настоящее время пишу две программы.

Первая программа успешно форматирует необработанные данные в файле XML в правильную структуру с отступом в виде дерева.

Вторая программа, где я застрял. Используя модуль minidom, я до сих пор мог генерировать вывод, который печатает одну строку из семи переменных, каждая из которых получена из указанного тега c в файле XML.

Проблема в том, что мне нужно чтобы получить несколько результатов для каждого тега элемента, из которого я извлекаю данные по всей длине документа.

Весь документ XML слишком велик для размещения на этом сайте и содержит конфиденциальные данные, поэтому Мне придется усечь и изменить его часть, чтобы вы могли хотя бы увидеть иерархии.

<ws_Worker>
    <ws_Summary>
      <ws_Employee_ID>555555</ws_Employee_ID>
    <ws_Name>John Doe</ws_Name>
    </ws_Summary>
  <ws_Eligibility ws_PriorValue="false">true</ws_Eligibility>
  <ws_Personal>
      <ws_Name_Data>
        <ws_Name_Type>Legal</ws_Name_Type>
      <ws_First_Name>John</ws_First_Name>
      <ws_Last_Name>Doe</ws_Last_Name>
      <ws_Formatted_Name>John Doe</ws_Formatted_Name>
      <ws_Reporting_Name>Doe, John</ws_Reporting_Name>
      </ws_Name_Data>
    <ws_Address_Data>
        <ws_Address_Type>WORK</ws_Address_Type>
      <ws_Address_Is_Public>true</ws_Address_Is_Public>
      <ws_Is_Primary>true</ws_Is_Primary>
      <ws_Address_Line_Data ws_Label="Address Line 1" ws_Type="ADDRESS_LINE_1">123 Sixth St.</ws_Address_Line_Data>
      <ws_Municipality>Baltimore</ws_Municipality>
      <ws_Region>Maryland</ws_Region>
      <ws_Postal_Code>12345</ws_Postal_Code>
      <ws_Country>US</ws_Country>
      </ws_Address_Data>
    <ws_Email_Data>
        <ws_Email_Type>WORK</ws_Email_Type>
      <ws_Email_Is_Public>true</ws_Email_Is_Public>
      <ws_Is_Primary>true</ws_Is_Primary>
      <ws_Email_Address ws_PriorValue="doeball@icloud.com">jdoe@company.com</ws_Email_Address>
      </ws_Email_Data>
    <ws_Tobacco_Use>false</ws_Tobacco_Use>
    </ws_Personal>
  <ws_Status>
      <ws_Employee_Status>Active</ws_Employee_Status>
    <ws_Active>true</ws_Active>
    <ws_Active_Status_Date>2020-01-01</ws_Active_Status_Date>
    <ws_Hire_Date>2020-01-01</ws_Hire_Date>
    <ws_Original_Hire_Date>2015-01-01</ws_Original_Hire_Date>
    <ws_Hire_Reason>Hire_Employee_Rehire_Employee_After_13_Weeks</ws_Hire_Reason>
    <ws_Continuous_Service_Date>2020-01-01</ws_Continuous_Service_Date>
    <ws_First_Day_of_Work>2020-01-01</ws_First_Day_of_Work>
    <ws_Retirement_Eligibility_Date>2016-10-01</ws_Retirement_Eligibility_Date>
    <ws_Retired>false</ws_Retired>
    <ws_Seniority_Date>2015-10-01</ws_Seniority_Date>
    <ws_Terminated>false</ws_Terminated>
    <ws_Not_Eligible_for_Hire>false</ws_Not_Eligible_for_Hire>
    <ws_Regrettable_Termination>false</ws_Regrettable_Termination>
    <ws_Resignation_Date>2018-11-01</ws_Resignation_Date>
    <ws_Not_Returning>false</ws_Not_Returning>
    <ws_Return_Unknown>false</ws_Return_Unknown>
    <ws_Has_International_Assignment>false</ws_Has_International_Assignment>
    <ws_Home_Country>US</ws_Home_Country>
    <ws_Rehire>true</ws_Rehire>
    </ws_Status>
  <ws_Position>
      <ws_Operation>NONE</ws_Operation>
    <ws_Position_ID>12345</ws_Position_ID>
    <ws_Effective_Date>2020-01-10</ws_Effective_Date>
    <ws_Primary_Position>true</ws_Primary_Position>
    <ws_Position_Title>Driver</ws_Position_Title>
    <ws_Business_Title>Driver</ws_Business_Title>
    <ws_Worker_Type>Regular</ws_Worker_Type>
    <ws_Position_Time_Type>Part_time</ws_Position_Time_Type>
    <ws_Job_Exempt>false</ws_Job_Exempt>
    <ws_Scheduled_Weekly_Hours>29</ws_Scheduled_Weekly_Hours>
    <ws_Default_Weekly_Hours>40</ws_Default_Weekly_Hours>
    <ws_Full_Time_Equivalent_Percentage>72.5</ws_Full_Time_Equivalent_Percentage>
    <ws_Exclude_from_Headcount>false</ws_Exclude_from_Headcount>
    <ws_Pay_Rate_Type>Hourly</ws_Pay_Rate_Type>
    <ws_Workers_Compensation_Code>1234</ws_Workers_Compensation_Code>
    <ws_Job_Profile>DRIVER</ws_Job_Profile>
    <ws_Management_Level>Individual Contributor</ws_Management_Level>
    <ws_Job_Family>DRV</ws_Job_Family>
    <ws_Business_Site>LOC_TOWN</ws_Business_Site>
    <ws_Business_Site_Name>Local Town</ws_Business_Site_Name>
    <ws_Business_Site_Address_Line_Data ws_Label="Address Line 1" ws_Type="ADDRESS_LINE_1">1234 Sixth St.</ws_Business_Site_Address_Line_Data>
    <ws_Business_Site_Municipality>Baltimore</ws_Business_Site_Municipality>
    <ws_Business_Site_Region>Maryland</ws_Business_Site_Region>
    <ws_Business_Site_Postal_Code>12345</ws_Business_Site_Postal_Code>
    <ws_Business_Site_Country>US</ws_Business_Site_Country>
    <ws_Supervisor>
        <ws_Operation>NONE</ws_Operation>
      <ws_Supervisor_ID>1234567</ws_Supervisor_ID>
      <ws_Supervisor_Name>Little Mac</ws_Supervisor_Name>
      </ws_Supervisor>
    </ws_Position>
  <ws_Additional_Information>
      <ws_WD_Username>John.Doe</ws_WD_Username>
    <ws_Last_4_SSN_Digits>1234</ws_Last_4_SSN_Digits>
    </ws_Additional_Information>
  </ws_Worker>

Помните, что в этом файле 36 других элементов.

Вот моя программа до сих пор:

from xml.dom import minidom

xmldoc = minidom.parse("//tocp-fs1/mydocs/mantonishak/Documents/Python/The_Hard_Way/Out.xml")

outworkers = xmldoc.getElementsByTagName("ws_Worker")[0]
# Knowing your heiarchy is important.  ws_Worker is at the top.  Asking the first value of the list.
outsummaries = outworkers.getElementsByTagName("ws_Summary")
outpersonals = outworkers.getElementsByTagName("ws_Personal")
outpositions = outworkers.getElementsByTagName("ws_Position")
outadditionals = outworkers.getElementsByTagName("ws_Additional_Information")

for outpersonal in outpersonals:
    desc = outpersonal.getElementsByTagName("ws_Formatted_Name")[0].firstChild.data
    # displays the user's Full Name
    for outsummary in outsummaries:
        desc2 = outsummary.getElementsByTagName("ws_Employee_ID")[0].firstChild.data
        # displays the user's Workday ID
    for location in outpositions:
       desc3 = location.getElementsByTagName("ws_Business_Site_Name")[0].firstChild.data
       # displays the user's current work location (Store Name)
    for title in outpositions:
        desc4 = title.getElementsByTagName("ws_Position_Title")[0].firstChild.data
        # displays the user's current title
    for email in outpersonals:
        desc5 = email.getElementsByTagName("ws_Email_Address")[0].firstChild.data
        lst = desc5.split("@")
        atsign = (lst[1])
        # This splits the ws_Email_Address value at the @ sign, removes it, and displays the string
        # to the right of the @ sign (which is the domain)
    for firstletter in outpersonals:
        desc6 = firstletter.getElementsByTagName("ws_First_Name")[0].firstChild.data
        firstletter = desc6[0]
        # This grabs the first letter of the ws_First_Name value so it can be combined later with
        # the ws_Last_Name value to create the username
    for lastname in outpersonals:
        desc7 = lastname.getElementsByTagName("ws_Last_Name")[0].firstChild.data
        username = (firstletter + desc7)
        # grabs the last name and combines with the first letter of the first name
        # this creates the username
    for ssn in outadditionals:
        desc8 = ssn.getElementsByTagName("ws_Last_4_SSN_Digits")[0].firstChild.data
        firstpass = desc6[0:2]
        lastpass = desc7[-2:]
        password = (firstpass + desc8 + lastpass)
        # this takes the first two chars of the ws_First_Name adds them as a string with the
        # ws_Last_4_SSN_Digits and the last two chars of ws_Last_Name.
    print("Full Name: %s, Employee ID: %s, Location: %s, Title: %s, Domain: %s, Username: %s, Password: %s" %
            (desc, desc2, desc3, desc4, atsign, username.lower(), password.lower()))
            # Creates the output in a straight horizontal line.  The .lower attributes for
            # username and password will format all characters in the strings above into lowercase.

И мой вывод выглядит так:

Full Name: John Doe, Employee ID: 1234567, Location: Local Town, Title: Driver, Domain: company.com, Username: jdoe, Password: jo1234oe

Итак, в строке 5 я думаю, что волхвы c должны бывает. Целое число [0] извлекает только дочерние теги из первого элемента. Если я изменяю это целое число на [1], оно вытягивает второе [2], вытягивает третье и т. Д.

Как мне построить al oop, который изменяет это целое число и совместно печатает выходные данные каждого элемента по всему файлу?

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Использование l xml и xpath:

from lxml import etree
employees = '''your xml above'''
doc = etree.fromstring(employees)
outpersonals = doc.xpath('//ws_Personal')
for op in outpersonals:
    fname = op.xpath('//ws_Formatted_Name/text()')[0]
    eid = op.xpath('//ws_Employee_ID/text()')[0]
    site = op.xpath('//ws_Business_Site_Name/text()')[0]
    title = op.xpath('//ws_Position_Title/text()')[0]
    email = op.xpath('//ws_Email_Address/text()')[0]
    first = op.xpath('//ws_First_Name/text()')[0]
    last = op.xpath('//ws_Last_Name/text()')[0]
    ssn = op.xpath('//ws_Last_4_SSN_Digits/text()')[0]


    print(f"Full Name: {fname}, Employee ID: {eid}, Location: {site}, Title: {title}, Domain: {email.split('@')[1]}, Username: {email.split('@')[0]}, Password: {fname[:2]+ssn+last[-2:]}")

Вывод:

Full Name: John Doe, Employee ID: 555555, Location: Local Town, Title: Driver, Domain: company.com, Username: jdoe, Password: Jo1234oe
0 голосов
/ 31 марта 2020

Вместо того, чтобы получать все теги отдельно, просто итерируйте по рабочим.

xmldo c .getElementsByTagName ("ws_Worker") вернет все экземпляры ws_worker в виде NodeList. Когда вы указываете первый с помощью [0], вы смотрите только на первый элемент.

Почему бы не выполнить итерацию по нему?

workers = xmldoc.getElementsByTagName("ws_Worker")
for node in workers:
    full_name = node.getElementsByTagName("ws_Formatted_Name").item(0).firstChild.nodeValue
    employee_id = node.getElementsByTagName("ws_Employee_ID").item(0).firstChild.nodeValue
    ... 

Теперь это обычные вещи DOM. XPATH намного чище, как только вы его получите. Потратьте несколько минут, чтобы прочитать об этом, потому что, как вы видите, ответ предоставлен Джеком Флитингом.

...