Confluence server REST API update page removes all macros?
Asked by allecti:

Hi,

I need to convert about 100 pages, their Page Properties is not in right format. I managed to convert table in Page Properties and table is updated to back page with REST API.

However, after page has been updated there is no macro's anymore. Page properties, Page tree and Expand macro's are gone.

What could be the reason for this? Wrong value in body': { 'storage': { 'representation': 'storage' ?


Answers:
author: Tobias Anstett _K15t_
body: Hi [@allecti](/t5/user/viewprofilepage/user-id/2094584),

Have you checked that the macros are still part of the storage format you send to the server?

Can you please add your REST request and some example payload, so I can have a closer look at it?

Best, Tobias

comments: author: allecti
body: This is what I get originally:
> {u'status': u'current', u'body': {u'_expandable': {u'export_view': u'', u'styled_view': u'', u'editor': u'', u'anonymous_export_view': u'', u'view': u''}, u'storage': {u'_expandable': {u'content': u'/rest/api/content/68335322'}, u'representation': u'storage', u'value': u'\<p class="auto-cursor-target"\>\<br /\>\</p\>\<ac:structured-macro ac:name="details" ac:schema-version="1" ac:macro-id="12aaf1ce-2b17-443c-8bae-ed3bb63adae4"\>\<ac:rich-text-body\>\<p class="auto-cursor-target"\>\<br /\>\</p\>\<table class="wrapped fixed-table"\>\<colgroup\>\<col style="width: 166.0px;" /\>\<col style="width: 132.0px;" /\>\<col style="width: 65.0px;" /\>\<col style="width: 159.0px;" /\>\</colgroup\>\<tbody\>\<tr\>\<th\>Status\</th\>\<td\>\<div class="content-wrapper"\>\<p\>\<ac:structured-macro ac:name="status" ac:schema-version="1" ac:macro-id="23bda9ed-398e-4543-b38f-b2136db1a9dc"\>\<ac:parameter ac:name="colour"\>Yellow\</ac:parameter\>\<ac:parameter ac:name="title"\>Draft\</ac:parameter\>\</ac:structured-macro\>\</p\>\</div\>\</td\>\<td class="highlight-grey" data-highlight-colour="grey"\>\<div class="content-wrapper"\>\<p\>\<strong\>Rev\</strong\>\</p\>\</div\>\</td\>\<td\>\<div class="content-wrapper"\>\<p\>0.3\</p\>\</div\>\</td\>\</tr\>\<tr\>\<th class="highlight-grey" colspan="1" data-highlight-colour="grey"\>Range of validity\</th\>\<td colspan="3"\>\<div class="content-wrapper"\>\<p\>general\</p\>\</div\>\</td\>\</tr\>\<tr\>\<th colspan="1"\>Period of validity\</th\>\<td colspan="1"\>\<br /\>\</td\>\<td colspan="1" style="text-align: center;"\>-\</td\>\<td colspan="1"\>\<br /\>\</td\>\</tr\>\<tr\>\<th colspan="1"\>Owner\</th\>\<td colspan="3"\>\<ac:link\>\<ri:user ri:userkey="ff808181604b387d0160e550b6320008" /\>\</ac:link\>\</td\>\</tr\>\</tbody\>

Python function to read data:

```
def read_data_storage(auth, page_id): 
 url = '{base}/{page_id}?expand=body.storage,macro'.format(base=BASE_URL, page_id=page_id) 
 r = requests.get( url, auth=auth, headers={'Content-Type': 'application/json', 'USER-AGENT': USER_AGENT} )
 r.raise_for_status()
 return r
```

After read I will do

```
json_text = read_data_storage(auth, options.pageid).text
json2 = json.loads(json_text) 
html_storage_txt = json2['body']['storage']['value']
```

data = html_storage_text.encode('utf-8')

```
<p class="auto-cursor-target"><br /></p>
<ac:structured-macro ac:name="details" ac:schema-version="1" ac:macro-id="12aaf1ce-2b17-443c-8bae-ed3bb63adae4">
<ac:rich-text-body>
<p class="auto-cursor-target"><br /></p><table class="wrapped fixed-table">
```

I am using lxml to modify.

tree = lxml.html.fromstring(data)

..... update 1st table content ....

html_string = lxml.html.tostring(tree, pretty_print=True)

```
<div>
<p class="auto-cursor-target"><br></p>
<structured-macro ac:name="details" ac:schema-version="1" ac:macro-id="12aaf1ce-2b17-443c-8bae-ed3bb63adae4"><rich-text-body><p class="auto-cursor-target"><br></p>
<table class="wrapped fixed-table">
```

write_data_storage(auth, html_string, options.pageid)

```
?def write_data_storage(auth, html, page_id, title = None): 
   info = get_page_info(auth, page_id)
   ver = int(info['version']['number']) + 1
   ancestors = get_page_ancestors(auth, page_id)
   anc = ancestors[-1] 
   del anc['_links'] 
   del anc['_expandable'] 
   del anc['extensions']
   if title is not None: info['title'] = title
   data = { 'id': str(page_id), 'type': 'page', 'title': info['title'], 
            'version': {'number': ver}, 'ancestors': [anc], 
            'body': { 'storage': 
                      { 'representation': 'storage', 
                         'value': str(html), 
                      } 
                    } 
          }
 data = json.dumps(data)
 url = '{base}/{page_id}'.format(base=BASE_URL, page_id=page_id)
 our_headers = {'Content-Type': 'application/json', 'USER-AGENT': USER_AGENT}
 r = requests.put( url, data=data, auth=auth, headers=our_headers )
 r.raise_for_status()
 print "Wrote '%s' version %d" % (info['title'], ver) print "URL: %s%d" % (VIEW_URL, page_id)
 return ""
```

Actually I have been playing it around now a while, trying to find out if storage / view representation matters. Now I get 400 error, need to figure out that.

Before I managed to update page but macro's were dropped out.

it would be nice to get even hints if I am doing something totally wrong.


author: Tobias Anstett _K15t_
body: Hi [@allecti](/t5/user/viewprofilepage/user-id/2094584),

The following request works for me:

```
{
 "id":"65658",
 "type":"page",
 "title":"new page",
 "space":{"key":"TEST"},
 "body": {
 "storage": {
 "value": "<p>This is the updated text for the new page</p>",
 "representation":"storage"
 }
 },
 "version":{"number": 44}
}
```

The major difference in my request is that I do not use the ancestors parameter and have a space parameter set.

Furthermore I would have a closer look into any html encode/decode operations.

The best is to try the requests in Postman or the Confluence Rest API browser first.

Best, Tobias


author: allecti
body: Thanks Tobias!

Yes, it is something to do now with encode/decode operations. My code works if I will use original data I got from Postman and I just update table part of that -\> everything is just like it should be.


author: Sandeep Jawalkar
body: [@allecti](/t5/user/viewprofilepage/user-id/2094584) hi,

can you share any code how u update table without encode


author: allecti
body: Actually found out that it is better to use request.content instead of request.text that seems to convert data and specially encoding it to string.

Everything started to work ok when I changed:

```
json_text = read_data_storage(auth, options.pageid).text
```

to

```
json_text = read_data_storage(auth, options.pageid).content
```


Tags: confluence-server

rest-api