Re: [xsl] How to write (existential) predicates with maps/Why is there no effective boolean value for a map?

Subject: Re: [xsl] How to write (existential) predicates with maps/Why is there no effective boolean value for a map?
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 12 Feb 2019 16:07:29 -0000
On 12.02.2019 15:40, Michael Kay mike@xxxxxxxxxxxx wrote:
I'm having trouble understanding/reproducing this. Can you supply a complete repro? (I.e., the source data that results in this error)


The example JSON is e.g.

{
    "locations" : [
      {
          "id" : "i1",
          "types" : [
              {
                "name" : "foo"
              },
              {
                "name" : "bar"
              }
          ]
      },
      {
          "id" : "i2",
          "types" : [
              {
                "name" : "baz"
              }
          ]
      },
      {
          "id" : "i3",
          "types" : [
              {
                "name" : "foo"
              },
              {
                "name" : "baz"
              }
          ]
      }
    ]
}

If you pass it to the parse-json function and use the result as the context item to the three XPath expressions I have posted then the first one gives that error while the other two return two maps.

A complete repro in XSLT is

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
	xmlns:xs="http://www.w3.org/2001/XMLSchema";
	exclude-result-prefixes="#all"
	version="3.0">

<xsl:output method="adaptive"/>

  <xsl:param name="json" as="xs:string">
{
    "locations" : [
      {
          "id" : "i1",
          "types" : [
              {
                "name" : "foo"
              },
              {
                "name" : "bar"
              }
          ]
      },
      {
          "id" : "i2",
          "types" : [
              {
                "name" : "baz"
              }
          ]
      },
      {
          "id" : "i3",
          "types" : [
              {
                "name" : "foo"
              },
              {
                "name" : "baz"
              }
          ]
      }
    ]
}
  </xsl:param>

<xsl:template match="/" name="xsl:initial-template">
<xsl:sequence select="parse-json($json)?locations?*[?types?*[?name = 'foo']]"/>
</xsl:template>


</xsl:stylesheet>




On 11 Feb 2019, at 12:09, Martin Honnen martin.honnen@xxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

When using XPath 3.1 (e.g. in XSLT 3) on maps I have found that I have to change my coding habit a bit when writing predicates that want to check the existence of some nested map, while I hoped to be able to write e.g.

?locations?*[?types?*[?name = 'foo']]

to select all (map) members of the "locations" array that have a "types" array with at least one (map) member having a property "name" with value "foo" I get an error

Effective boolean value is not defined for sequence starting with an atomic value other than a boolean, number, or string


So in contrast to my experience with writing predicates on XML it seems for maps I have to explicitly use the "exists" function e.g.


?locations?*[exists(?types?*[?name = 'foo'])]

or a "some .. in" expression

?locations?*[some $m in ?types?* satisfies $m?name = 'foo']


Is there any more compact way to write such a check?


What is the reason that the effective boolean value was not extended to give true for a sequence with a map?

Current Thread