# JSONata only return existing items

**URL:** <https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523>\
**Category:** General\
**Created:** [11 January 2025 06:44 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523 "2025-01-11T06:44:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [11 January 2025 06:44 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/1 "2025-01-11T06:44:12Z")

</div>

I have an object and an array of urls.

example array:

`['http://airbnb.design/feed/','http://nautil.us/rss/all']`

example object:

```auto
{
  "attr": { "version": "1.1" },
  "head": [{ "title": ["some opml"] }],
  "body": [
    {
      "outline": [
        {
          "attr": { "text": "Design", "title": "Design" },
          "outline": [
            { "attr": { "text": "Airbnb Design", "title": "Airbnb Design", "description": "", "type": "rss", "version": "RSS", "htmlUrl": "https://airbnb.design/", "xmlUrl": "http://airbnb.design/feed/" } }, 
            { "attr": { "text": "web.dev: Blog", "title": "web.dev: Blog", "description": "", "type": "rss", "version": "RSS", "htmlUrl": "https://web.dev/blog/", "xmlUrl": "https://web.dev/feed.xml" } }]
        },
        {
          "attr": { "text": "Science", "title": "Science" },
          "outline": [
            { "attr": { "text": "Nature", "title": "Nature", "description": "", "type": "rss", "version": "RSS", "htmlUrl": "http://feeds.nature.com/nature/rss/current", "xmlUrl": "http://www.nature.com/nature/current_issue/rss" } }, 
            { "attr": { "text": "Nautilus", "title": "Nautilus", "description": "", "type": "rss", "version": "RSS", "htmlUrl": "", "xmlUrl": "http://nautil.us/rss/all" } }]
        }
      ]
    }
  ]
}

```

I want to remove the containing object when the xmlUrl matches (ie. the urls don't work, so exclude/remove them)

I see I can do something like `**[xmlUrl!='http://nautil.us/rss/all']` but that only returns an array excluding the object containing the url.

Using a javascript function became somewhat convoluted because of the nested properties and was hoping that jsonata could make quick work of this...if I only would understand it :')

---

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [11 January 2025 07:55 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/2 "2025-01-11T07:55:37Z")

</div>

With the help of qwen2.5-coder 14B locally on my mac, I was able to generate a javascript function that works.

```auto
function removeOutlineByXmlUrl(inputObject, xmlUrlToRemove) {

    function processOutline(outlineArray) {
        return outlineArray.filter(item => {
            if (item.outline && item.outline.length > 0) {
                item.outline = processOutline(item.outline);
            }
            return item.attr.xmlUrl !== xmlUrlToRemove;
        });
    }

    const resultObject = inputObject

    if (resultObject.body && resultObject.body.length > 0) {
        resultObject.body.forEach(bodyItem => {
            if (bodyItem.outline && bodyItem.outline.length > 0) {
                bodyItem.outline = processOutline(bodyItem.outline);
            }
        });
    }

    return resultObject;
}

```

I dont think I have ever used recursion like this myself, nifty, you learn every day.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [11 January 2025 08:39 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/3 "2025-01-11T08:39:36Z")

</div>

If you only want to remove the object in the msg.payload.body[0].outline would this not do it. Or does the body have more than 1 array element

```auto
[{"id":"5659df32a49fb39c","type":"inject","z":"667cec54c048503c","name":"","props":[{"p":"payload"},{"p":"urls","v":"[\"http://airbnb.design/feed/\",\"http://nautil.us/rss/all\"]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{ \"attr\": { \"version\": \"1.1\" }, \"head\": [{ \"title\": [\"some opml\"] }], \"body\": [{ \"outline\": [ { \"attr\": { \"text\": \"Design\", \"title\": \"Design\" }, \"outline\": [ { \"attr\": { \"text\": \"Airbnb Design\", \"title\": \"Airbnb Design\", \"description\": \"\", \"type\": \"rss\", \"version\": \"RSS\", \"htmlUrl\": \"https://airbnb.design/\", \"xmlUrl\": \"http://airbnb.design/feed/\" } }, { \"attr\": { \"text\": \"web.dev: Blog\", \"title\": \"web.dev: Blog\", \"description\": \"\", \"type\": \"rss\", \"version\": \"RSS\", \"htmlUrl\": \"https://web.dev/blog/\", \"xmlUrl\": \"https://web.dev/feed.xml\" } }] }, { \"attr\": { \"text\": \"Science\", \"title\": \"Science\" }, \"outline\": [{ \"attr\": { \"text\": \"Nature\", \"title\": \"Nature\", \"description\": \"\", \"type\": \"rss\", \"version\": \"RSS\", \"htmlUrl\": \"http://feeds.nature.com/nature/rss/current\", \"xmlUrl\": \"http://www.nature.com/nature/current_issue/rss\" } }, { \"attr\": { \"text\": \"Nautilus\", \"title\": \"Nautilus\", \"description\": \"\", \"type\": \"rss\", \"version\": \"RSS\", \"htmlUrl\": \"\", \"xmlUrl\": \"http://nautil.us/rss/all\" } }] } ] } ] }","payloadType":"json","x":510,"y":1120,"wires":[["fc362e0308a48ac0"]]},{"id":"fc362e0308a48ac0","type":"change","z":"667cec54c048503c","name":"","rules":[{"t":"set","p":"payload.body[0].outline","pt":"msg","to":"[$filter($$.payload.body[0].outline, function($v){\t $count($v.**.xmlUrl[$ in $$.urls]) = 0\t})]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":1120,"wires":[["984cf197480bc4af"]]},{"id":"984cf197480bc4af","type":"debug","z":"667cec54c048503c","name":"debug 2579","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1010,"y":1120,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [11 January 2025 10:19 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/4 "2025-01-11T10:19:42Z")

</div>

This deleted all items in the body ?

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [11 January 2025 10:40 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/5 "2025-01-11T10:40:23Z")

</div>

No, it removes all objects from the `msg.payloadbody[].outline` array, that has a xmlURL in the `msg.url array`.  
Output

```auto
{
    "attr": {
        "version": "1.1"
    },
    "head": [
        {
            "title": [
                "some opml"
            ]
        }
    ],
    "body": [
        {
            "outline": []
        }
    ]
}

```

If I am mistaken with what you require the output to be, please supply what the output should look like.

---

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [11 January 2025 10:48 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/6 "2025-01-11T10:48:49Z")

</div>

With this as input:

`['http://airbnb.design/feed/','http://nautil.us/rss/all']`

should produce this as output (ie. remove the object where the url appears under xmlUrl.

```auto
{
  "attr": { "version": "1.1" },
  "head": [{ "title": ["some opml"] }],
  "body": [
    {
      "outline": [
        {
          "attr": { "text": "Design", "title": "Design" },
          "outline": [
            
            { "attr": { "text": "web.dev: Blog", "title": "web.dev: Blog", "description": "", "type": "rss", "version": "RSS", "htmlUrl": "https://web.dev/blog/", "xmlUrl": "https://web.dev/feed.xml" } }]
        },
        {
          "attr": { "text": "Science", "title": "Science" },
          "outline": [
            { "attr": { "text": "Nature", "title": "Nature", "description": "", "type": "rss", "version": "RSS", "htmlUrl": "http://feeds.nature.com/nature/rss/current", "xmlUrl": "http://www.nature.com/nature/current_issue/rss" } }
          ]
        }
      ]
    }
  ]
}

```

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [11 January 2025 11:39 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/7 "2025-01-11T11:39:53Z")

</div>

Try

```auto
[$map($$.payload.body[0].outline, function($v){
    $v ~> |$|{
        "outline": [$filter($.outline, function($vf){
            $not($vf.attr.xmlUrl in $$.urls)
        })]
    }|
})]

```

Or more concise

```auto
[$$.payload.body[0].outline ~> |$|{
    "outline": [$filter($.outline, function($vf){
        $not($vf.*.xmlUrl in $$.urls)
    })]
}|]

```

[edit] Wondering if [node-red-contrib-fastxml (node) - Node-RED](https://flows.nodered.org/node/node-red-contrib-fastxml) may return a more workable object. (guessing that you object is parsed from an xml)

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [11 April 2025 11:40 UTC](https://discourse.nodered.org/t/jsonata-only-return-existing-items/94523/8 "2025-04-11T11:40:07Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
