liquidfetchxml

Reformat list items with Liquid


I have a Dynamics 365 API which is FetchXML & Liquid.

Nothing wrong with API, that all works well. Most of the fields the API pulls from in Dataverse are text fields. So when staff do (stupid) things like copy\paste from a Word document (as the text field might support 1000 characters for a 'description'). We've got the liquid handling line breaks & quotation marks, but I'm trying to get it handle list items.

So lets say i copy across this into the text field (screen capture from MS word in dark mode)

enter image description here

I'm converting line breaks to <br>, im changing the quotation marks from "&quot;" to "\&quot;" to escape it - these both work. Then trying to change a "&tab;" to a line break <br> (as i assume the bullets have tabs) & changing the bullet "•" to "&minus;"... but i appear to be missing something as the JSON response is still broken.

Here's my liquid code. at the moment im just testing & trying to get the "nxn_edmspeakerabout" field to work.

{ "Entity" : 
  [
    {% for result in my_query.results.entities %}
      {
        "msevtmgt_name" : "{{ result['msevtmgt_name'] }}",
        "ceda_speakerrole" : "{{ result['ceda_speakerrole'].value }}",
        "ceda_speakerrole_label" : "{{ result.ceda_speakerrole.label }}",
        "msevtmgt_eventid" : "{{ result['msevtmgt_event'].id }}",
        "msevtmgt_event_label" : "{{ result['msevtmgt_event'].name }}",
        "msevtmgt_speakerid" : "{{ result['msevtmgt_speaker'].id }}",
        "msevtmgt_speaker_label" : "{{ result['msevtmgt_speaker'].name }}",
        "nxn_edmspeakerabout" : "{{ result['nxn_edmspeakerabout'] | replace: "\n", "<br>" | replace: "&quot;", "\&quot;" | replace: "&tab;", "<br>" | replace: "•", "&minus;" | escape }}",
        "nxn_edmspeakercompany" : "{{ result['nxn_edmspeakercompany'] }}",
        "nxn_edmspeakerposition" : "{{ result['nxn_edmspeakerposition'] }}",
        "msevtmgt_description" : "{{ result['msevtmgt_description'] | replace: "\n", "<br>" | replace: "&quot;", "\&quot;" | escape  }}",
        "nxn_edmimageurl" : "{{ result['nxn_edmimageurl'] }}",
        "ceda_order" : "{{ result['ceda_order'] }}"
      }

      {% unless forloop.last %},{% endunless %}

    {% endfor %}
  ] 
}

This is the API JSON response in my browser

{ "Entity" : [ 
 { 
   "msevtmgt_name" : "The Hon. Chris Bowen MP", 
   "ceda_speakerrole" : "2", 
   "ceda_speakerrole_label" : "Speaker", 
   "msevtmgt_eventid" : "542b064e-7616-428c-8b9b-12e941be4d46", 
   "msevtmgt_event_label" : "Livestream: Rewiring the Nation – The Hon. Chris Bowen", 
   "msevtmgt_speakerid" : "a8d51ab4-cf1a-ee11-8f6c-000d3a7943d3", 
   "msevtmgt_speaker_label" : "The Hon. Chris Bowen MP", 
   "nxn_edmspeakerabout" : "This is “quote”<br>This is bullet points:<br>&minus; Item 1<br>&minus; Item 2<br>&minus; Item 3", 
   "nxn_edmspeakercompany" : "", 
   "nxn_edmspeakerposition" : "", 
   "msevtmgt_description" : "The is the "Speaker Description" quote test", 
   "nxn_edmimageurl" : "https://assets-oce.mkt.dynamics.com/7b7fa636-f815-4880-b15d-77d70348ee1e/digitalassets/images/11491d16-da34-ee11-bdf4-6045bd3d3194?ts=638269789794222007", 
   "ceda_order" : "" 
  } 
] } 

If i get the source of the browser JSON & paste it in Notepad++, i can see there's a character there (highlighted) but no idea what it is, as its not a tab or a space. enter image description here

Update: So looking in a hex editor apparently the character is (hex) 09, which as unicode is "&#9;", but if i add replace: "&#9;", "&nbsp;" to my liquid, the character is still there.


Solution

  • I worked it out myself...

    The tab on the left side of the bullet point can only be addressed with &tab; The tab on the right side of the bullet point can only be addressed with \t

    Both &tab; & \t have a hex value of 09 ~ thus the unicode version of "&#x9;", but apparently these aren't equal to each other (or the same thing)... at least in this Microsoft world.

    So liquid filtering all working, and code looks like this:

    { "Entity" : 
      [
        {% for result in my_query.results.entities %}
          {
            "msevtmgt_name" : "{{ result['msevtmgt_name'] }}",
            "ceda_speakerrole" : "{{ result['ceda_speakerrole'].value }}",
            "ceda_speakerrole_label" : "{{ result.ceda_speakerrole.label }}",
            "msevtmgt_eventid" : "{{ result['msevtmgt_event'].id }}",
            "msevtmgt_event_label" : "{{ result['msevtmgt_event'].name }}",
            "msevtmgt_speakerid" : "{{ result['msevtmgt_speaker'].id }}",
            "msevtmgt_speaker_label" : "{{ result['msevtmgt_speaker'].name }}",
            "nxn_edmspeakerabout" : "{{ result['nxn_edmspeakerabout'] | replace: "\n", "<br>" | replace: "&quot;", "\&quot;" | replace: "&tab;", "<br>" | replace: "•", "&minus;" | replace: "\t", "&nbsp;" | escape }}",
            "nxn_edmspeakercompany" : "{{ result['nxn_edmspeakercompany'] }}",
            "nxn_edmspeakerposition" : "{{ result['nxn_edmspeakerposition'] }}",
            "msevtmgt_description" : "{{ result['msevtmgt_description'] | replace: "\n", "<br>" | replace: "&quot;", "\&quot;" | replace: "&tab;", "<br>" | replace: "•", "&minus;" | replace: "\t", "&nbsp;" | escape  }}",
            "nxn_edmimageurl" : "{{ result['nxn_edmimageurl'] }}",
            "ceda_order" : "{{ result['ceda_order'] }}"
          }
    
          {% unless forloop.last %},{% endunless %}
    
        {% endfor %}
      ] 
    }