3 Replies Latest reply on Oct 26, 2017 8:50 AM by Russell Goldin

    Parsing REST API XML

    shoba Hari

      Hi There,


      We are trying to parse XML using REST API "Query Workbooks for Site" to get the workbook id, workbook name, tags associated with the workbook and the project it belongs to.

      Expected Response body:


        <pagination pageNumber="page-number"
      total-available" />


          <workbook id="workbook-id" name="name"
      datetime-updated"  >

            <project id="project-id" name="project-name" />

            <owner id="user-id" />


              <tag label="tag"/>

              ... additional tags ...



         ... additional workbooks ...



      We are unable to get the project id, project name, owner id and the tags associated with the workbook


      We use the below to parse XML.

      import xml.etree.ElementTree as ET

      Below is the query

      def query_workbooks():
          Returns a list of workbooks on the site (a list of <workbook> elements).
          The function paginates over results (if required) using a page size of 100.
          #GET /api/api-version/sites/site-id/workbooks?pageSize=page-size&pageNumber=page-number
          url = SERVER + "/api/{0}/sites/{1}/workbooks".format(API_VERSION,SITE_ID)

          pageNum, pageSize = 1, 100

          paged_url = url + "?pageSize={}&pageNumber={}".format(pageSize, pageNum)

          server_response = requests.get(paged_url, headers={"x-tableau-auth": TOKEN},verify=False)
          server_response.encoding = "utf-8";
          if server_response.status_code != 200:
          xml_response = ET.fromstring(_encode_for_display(server_response.text))

          total_count_of_workbooks = int(xml_response.find('t:pagination', namespaces=xmlns).attrib.get('totalAvailable'))
          if total_count_of_workbooks > pageSize:
              workbooks = []
              workbooks.extend(xml_response.findall('.//t:workbooks/workbook', namespaces=xmlns))
              number_of_pages = int(math.ceil(total_count_of_workbooks / pageSize))
              # Starts from page 2 because page 1 has already been returned
              for page in range(2, number_of_pages + 1):
                  paged_url = url + "?pageSize={}&pageNumber={}".format(pageSize, page)
                  server_response = requests.get(paged_url, headers={"x-tableau-auth": TOKEN},verify=False)
                  if server_response.status_code != 200:
                  workbooks_from_page = ET.fromstring(_encode_for_display(server_response.text)).findall('.//t:workbook', namespaces=xmlns)
              workbooks = xml_response.findall('.//t:workbook', namespaces=xmlns)
          return workbooks


      for WB in list_of_workbooks:

              print("IN A WB : "+ str(WB))


              a = a + 1

              print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :" + str(a))

              print("WB #" + str(a) + "           is:" +  WB.get('name'))

              print("              id is:        " +  WB.get('id'))

              print("      contentUrl is:" +  WB.get('contentUrl'))

              print("       updatedAt is:" +  WB.get('updatedAt'))



          for tag in list_of_tags:

              print("IN A TAG"  + tag.get(tag))


      Can someone help us to understand what's wrong with this query, why we are not able to get the tags, project id, project name, owner id in the response.



        • 1. Re: Parsing REST API XML

          Hello Shoba,


          I do not have much experience with the REST API myself. Though I would attempt to post on the Tableau Community developer portal: Developer Forums 


          Within the developer portal is a section specifically for the REST API.



          • 2. Re: Parsing REST API XML
            Jason Scott

            I know this is late to the party but I actually just solved this on my end.


            You need to change this line in the else statement


                    workbooks = xml_response.findall('.//t:workbook', namespaces=xmlns)


                return workbooks




            workbooks = xml_response


            then in for WB in list_of_workbooks:

            I needed to add this

            i = 0

            for workbook in query_workbooks_site(site_id):

                 for books in workbook.findall('.//{http://tableau.com/api}workbook'):

                      rcd[0] = books.get('name')

                      rcd[1] = books.get('contentUrl')

                      rcd[2] = workbook.findall('.//{http://tableau.com/api}project')[i].get('name')

                      rcd[3] = books.get('updatedAt')

                      rcd[4] = books.get('size')

                      i = i + 1


            The formatting is different due to the tool i'm using however what this will allow you to do is use xpath to grab the correct elements as you iterate through the workbooks.

            So to get tags you can just use this
            workbook.findall('.//{http://tableau.com/api}tag')[i].get('label') which you might need to iterate though.



            1 of 1 people found this helpful
            • 3. Re: Parsing REST API XML
              Russell Goldin

              You might be interested in looking at the Server-client-python or Tableau_Tools which are both wrappers around our API and handle the XML in the background.  You can either look at these implementations to see how they coded the responses or use them directly in your code.

              1 of 1 people found this helpful