Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jaspersoft-Python-LXML-CSV-Variable子标签_Python_Xml_Csv_Lxml - Fatal编程技术网

Jaspersoft-Python-LXML-CSV-Variable子标签

Jaspersoft-Python-LXML-CSV-Variable子标签,python,xml,csv,lxml,Python,Xml,Csv,Lxml,我正在尝试将Jaspersoft服务器上的用户列表导出为CSV格式,因为我们目前无法访问数据库或任何管理面板,每次需要列表时,我们都必须提交支持通知单并等待2天。我想我会用RESTAPI和python试试运气,在请求模块的帮助下,我成功地导出了保存这些信息的XML。提取的XML的格式如下所示 示例XML: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <users> <user>

我正在尝试将Jaspersoft服务器上的用户列表导出为CSV格式,因为我们目前无法访问数据库或任何管理面板,每次需要列表时,我们都必须提交支持通知单并等待2天。我想我会用RESTAPI和python试试运气,在请求模块的帮助下,我成功地导出了保存这些信息的XML。提取的XML的格式如下所示

示例XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
    <user>
        <emailAddress>doejoe@email.com</emailAddress>
        <enabled>true</enabled>
        <fullName>John Doe</fullName>
        <username>doejoe</username>
        <roles>
            <role>
                <externallyDefined>false</externallyDefined>
                <name>MANAGER</name>
                <desc>Beatings will continue until morale improves</desc>
            </role>
            <role>
                <externallyDefined>false</externallyDefined>
                <name>DIRECTOR</name>
            </role>
        </roles>
    </user>
     <user>
        <emailAddress>kathysmith@email.com</emailAddress>
        <enabled>true</enabled>
        <fullName>Kathy Smith</fullName>
        <username>kathysmith</username>
        <externallyDefined>false</externallyDefined>
        <roles>
            <role>
                <externallyDefined>false</externallyDefined>
                <name>USER</name>
                <desc>User Description</desc>
            </role>
            <role>
                <externallyDefined>false</externallyDefined>
                <name>SUPER_MANAGER</name>
                <desc>Super Manager description.</desc>
            </role>
             <role>
                <externallyDefined>false</externallyDefined>
                <name>SUPER_DIRECTOR</name>
            </role>
        </roles>
    </user>
</users>
正如你所知道的——我不是一个程序员,也不是一个程序员,所以如果你的眼睛流血的话,我向你道歉——我是在3周前开始学习python的。我的代码不起作用有以下几个原因:

  • 每个用户可以有1到X个角色,因此我找到的所有示例都有标准数量的子对象
  • 某些用户属性可能丢失,因此找不到时出错
  • 某些属性正在重复自身,例如,在用户和角色中都定义了外部属性
  • 我的循环将每个字母导出到一个单独的单元格,但我相信这是我能解决的问题
我的最终目标是这样的:

import lxml.etree as ET
import csv

# load file
tree = ET.parse('users.xml')
# iterate through each user tag
users = tree.findall('.//user')

# just w mode, no wb. wb is for binary data
with open('user_list.csv', "w") as csv_file:
    writer = csv.writer(csv_file, delimiter=',')
    # write headers
    writer.writerow([
        'email', 'enabled', 'externallyDefined',
        'fullName', 'tenantId', 'username', 'director',
        'manager', 'user', 'super manager', 'super director'
        ])
    for user in users:
        email = user.find('emailAddress').text
        enabled = user.find('enabled').text

        # process optional element
        externallyDefined = user.find('externallyDefined')
        if externallyDefined is not None:
            externallyDefined = externallyDefined.text

        fullName = user.find('fullName').text

        # another optional element
        tenantId = user.find('tenantId')
        if tenantId is not None:
            tenantId = tenantId.text

        username = user.find('username').text

        # collect nested elements (roles)
        user_roles = {}
        roles = user.find('roles').findall('role')
        for role in roles:
            user_roles[role.find('name').text] = True

        writer.writerow([
            email, enabled, externallyDefined, fullName,
            tenantId,  username, user_roles.get('DIRECTOR'),
            user_roles.get('MANAGER'), user_roles.get('USER'),
            user_roles.get('SUPER_MANAGER'), user_roles.get('SUPER_DIRECTOR')
            ])


对于我如何解决这些问题的任何帮助/指导,我将不胜感激,因为此时我完全不知所措。祝你周末愉快

试试这样的方法:

import lxml.etree as ET
import csv

# load file
tree = ET.parse('users.xml')
# iterate through each user tag
users = tree.findall('.//user')

# just w mode, no wb. wb is for binary data
with open('user_list.csv', "w") as csv_file:
    writer = csv.writer(csv_file, delimiter=',')
    # write headers
    writer.writerow([
        'email', 'enabled', 'externallyDefined',
        'fullName', 'tenantId', 'username', 'director',
        'manager', 'user', 'super manager', 'super director'
        ])
    for user in users:
        email = user.find('emailAddress').text
        enabled = user.find('enabled').text

        # process optional element
        externallyDefined = user.find('externallyDefined')
        if externallyDefined is not None:
            externallyDefined = externallyDefined.text

        fullName = user.find('fullName').text

        # another optional element
        tenantId = user.find('tenantId')
        if tenantId is not None:
            tenantId = tenantId.text

        username = user.find('username').text

        # collect nested elements (roles)
        user_roles = {}
        roles = user.find('roles').findall('role')
        for role in roles:
            user_roles[role.find('name').text] = True

        writer.writerow([
            email, enabled, externallyDefined, fullName,
            tenantId,  username, user_roles.get('DIRECTOR'),
            user_roles.get('MANAGER'), user_roles.get('USER'),
            user_roles.get('SUPER_MANAGER'), user_roles.get('SUPER_DIRECTOR')
            ])

一般的方法很简单

  • 迭代所有用户
  • 提取每个用户的固定XPath表达式集的值
  • 将这些值写入CSV文件
…我们可以概括为:

  • 迭代初始XPath表达式的所有结果
  • 提取每个结果的固定XPath表达式集的值
  • 将其作为嵌套列表返回(即“列的行”)
为此,我们基本上需要

  • 一个函数,我们称之为
    extract_val()
    ,它接受一个XML节点,对其运行XPath,并返回第一个找到的值。
    这是必要的,因为lxml的
    .xpath()
    方法既有简单值(字符串、布尔值、浮点值)也有节点或值列表
  • 一个函数,比如说
    xml\u extract()
    ,它可以获取一个xml文档,迭代对象,并将我们的
    extract\u val()
    应用到每个对象,返回一个值列表
  • 我们要提取的XPath列表-这将对应于我们稍后的CSV列
  • 最后,
    csv.writerows()
    一次写出它们
代码:

import lxml.etree as ET

def extract_val(context_node, xpath):
    '''Extracts one value from an XML node'''
    result = context_node.xpath(xpath)
    if isinstance(result, list):
        result = result[0] if len(result) > 0 else None
    if isinstance(result, ET._Element):
        return result.text
    if isinstance(result, (bool, float, str)):
        return result

def xml_extract(tree_or_path, object_xpath, property_xpaths):
    '''Extracts lists of values from an XML tree (or path to an XML file)'''
    if isinstance(tree_or_path, ET._ElementTree):
        tree = tree_or_path
    if isinstance(tree_or_path, str):
        tree = ET.parse(tree_or_path)
    for elem in tree.xpath(object_xpath):
        yield [extract_val(elem, path) for path in property_xpaths]

#----------------------------------------------------------------------
import csv

with open('user_list.csv', 'w', encoding='utf8', newline='') as csv_file:
    writer = csv.writer(csv_file, delimiter=',')
    rows = xml_extract('Format.xml', '//user', [
        'emailAddress',
        'enabled',
        'externallyDefined',
        'fullName',
        'tenantId',
        'username',
        'count(roles/role[name = "DIRECTOR"]) > 0',
        'count(roles/role[name = "MANAGER"]) > 0',
    ])
    writer.writerows(rows)

这种方法非常灵活,可以从任何XML中提取值表(您可能希望这样做),以便重用。

您应该包括所需的输出,特别是对于重复的内容和具有多个角色的人员。@Tomalak谢谢,我添加了一个屏幕截图,显示了我们为数百名用户手动执行的操作。任何接近这一点的都可以!非常感谢你!唯一的问题[这是我没有解释的过错]是示例只包含5个角色。是否有任何方法可以从XML中读取所有独特的角色并填写它们?如果没有,那没关系-我仍然可以硬编码它们@HRG,是的,这是可能的。但我不知道开销是否会很大(对于大型xml文件)。@HRG还有一个问题——角色列的顺序可能是随机的,因为我使用set来收集它们。如果需要,您可以按字母顺序对角色集合进行排序,也可以只对角色列表进行硬编码。非常感谢您-数据集非常小[少于1000个用户],因此处理时间不到一秒钟。我觉得很好,非常感谢!