【问题标题】:Python API XML parsing - NamespacesPython API XML 解析 - 命名空间
【发布时间】:2017-03-13 22:13:40
【问题描述】:

我正在使用 Python 通过 API 解析从我的 Tableau 服务器返回的一些 XML。涉及命名空间,我想我可能对它们的工作原理缺乏一些基本的了解。这是我的 XML 的样子:

<tsResponse version-and-namespace-settings>
  <parent type="Project" id="1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e" />
  <permissions>
    <workbook id="1a1b1c1d-2e2f-2a2b-3c3d-3e3f4a4b4c4d" name="Finance">
      <owner id="9f9e9d9c-8b8a-8f8e-7d7c-7b7a6f6d6e6d"/>
    </workbook>
    <granteeCapabilities>
      <group id="1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"/>
      <capabilities>
        <capability name="Read" mode="Allow"/>
        <capability name="Filter" mode="Allow"/>
        <capability name="ViewUnderlyingData" mode="Allow"/>
        <capability name="ExportImage" mode="Allow"/>
        <capability name="ExportData" mode="Allow"/>
        <capability name="AddComment" mode="Allow"/>
        <capability name="ViewComments" mode="Allow"/>
        <capability name="ShareView" mode="Allow"/>
      </capabilities>
    </granteeCapabilities>
  </permissions>
</tsResponse>

这是我正在运行的代码,已精简到出现问题的位置。我的目标是首先识别给定工作簿 ID 下的每个组 ID,然后找到该组下的每个功能。

xmlns = {'t': 'http://tableau.com/api'}
test_response1 = []
test_response2 = []

url = "tableau.my.org/api/2.4/sites/siteid/workbooks/workbookid/permissions?pageSize=1000".format()
server_response_WB2 = requests.get(url, headers={'x-tableau-auth': auth_token})
test_response1.append(server_response_WB2.text)
server_response_WB2 = ET.fromstring(_encode_for_display(server_response_WB2.text))
permissions = server_response_WB2.findall('.//t:permissions', namespaces=xmlns)

for permission in permissions:
    capabilities = permission.findall('granteeCapabilities')
    test_response2.append(capabilities)

print test_response1
print test_response2

test_response1 包含如下列表:

[[<Element '{http://tableau.com/api}permissions' at 0x3c07d70>], 
[<Element '{http://tableau.com/api}permissions' at 0x3bb8dd0>]]

test_response2 然而,返回一个空列表列表:

[[], [], []]

在上面的代码中,我正在寻找“granteeCapabilities”作为标签。我还尝试使用命名空间将其作为路径查找,如下所示:

capabilities = permission.findall('.//t:permissions/granteeCapabilities', namespaces=xmlns)

这会返回相同的结果。空列表的列表。为什么我可以找到权限下的数据,但不能找到较低级别的数据?

【问题讨论】:

    标签: python xml api xml-namespaces tableau-api


    【解决方案1】:

    如果问题可能与 XML 命名空间有关,那么您真的不应该在问题中忽略 XML 的命名空间部分,因为它是诊断问题和编写有效解决方案的基础。

    我怀疑命名空间 http://tableau.com/api 在 XML 中被声明为默认命名空间(不带前缀的命名空间),在这种情况下,所有不带前缀的后代元素都会隐式地从祖先那里继承相同的命名空间。这可以解释为什么granteeCapabilities 不适合您,您也应该尝试在此处添加前缀t

    capabilities = permission.findall('t:granteeCapabilities', namespaces=xmlns)
    

    如果您不需要来自permissionselement 的任何信息,您可以直接获取granteeCapabilities

    capabilities = root.findall('.//t:granteeCapabilities', namespaces=xmlns)
    

    这是一个简短但完整的示例,演示了解决方案:

    raw = '''<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="w3.org/2001/XMLSchema-instance" xsi:schemaLocation="tableau/com/api tableau.com/api/ts-api-2.4.xsd">
      <parent type="Project" id="1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e" />
      <permissions>
        <granteeCapabilities>
          <group id="1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"/>
          <capabilities>
            ....
          </capabilities>
        </granteeCapabilities>
      </permissions>
    </tsResponse>'''
    
    from xml.etree import ElementTree as ET
    root = ET.fromstring(raw)
    xmlns = {'t': 'http://tableau.com/api'}
    permissions = root.findall('.//t:permissions', namespaces=xmlns)
    for permission in permissions:
        capabilities = permission.findall('t:granteeCapabilities', namespaces=xmlns)
        print capabilities
    

    eval.in demo

    输出:

    [<Element '{http://tableau.com/api}granteeCapabilities' at 0x402f430c>]
    

    【讨论】:

    • 我试过这个表格,但仍然得到一个空列表的列表。我同意你关于命名空间的观点,但我不知道在哪里可以找到它。我正在修改 Tableau 提供的示例代码。关于如何使用 Python 从 XML 中读取命名空间,您有什么建议吗?
    • 您收到的实际 XML 字符串是什么样的? (尤其是这部分&lt;tsResponse version-and-namespace-settings&gt;)。你不能打印或保存到文件:_encode_for_display(server_response_WB2.text) 吗?
    • 开头写着:tableau.com/api" xmlns: xsi="w3.org/2001/XMLSchema-instance" xsi:schemaLocation="tableau/com/api tableau.com/api/ts-api-2.4.xsd"> 我试着导航到那些网址,但那里什么都没有。
    • @JeremyReal 命名空间 URI 只是一个标识符,不一定是您可以导航到的真实 URL。我只是稍微更新了代码,因为您已经在 permission 元素中,XPath 不应该直接提及 t:granteeCapabilities。如果这不起作用,请尝试.//t:granteeCapabilities
    • @JeremyReal 也是 URL,根据您的评论,应该是 xmlns = {'t': 'tableau.com/api'}(即没有 http://,或者这只是一个复制粘贴问题?)...
    猜你喜欢
    • 2018-07-15
    • 2010-11-08
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2021-05-03
    • 2014-01-10
    相关资源
    最近更新 更多