Document the quoting rule in the selector syntax

An unquoted pset, prop, key or value may not contain any of , . = > < * !
or whitespace. This was never stated, and the only motivation the docs gave
for quoting was the "Level 3" example having a space, so there was nothing
to suggest that Pset_WallCommon.ThermalTransmittance=1.5 is a syntax error
while FireRating=2HR is fine. Decimal numbers are the common way to hit it.

State the rule where the reader meets values, in a new subsection under each
of the two value tables. The two grammars exclude different characters, so
the element value section states its own set and only the delta. Note that
all of these characters are a syntax error except the comma, which is read
as the filter separator instead, so Name=Foo,IfcWall silently means "named
Foo and an IfcWall" rather than matching the literal value.

Also fix the Query filter example, which had the same problem in the file
itself: query:types.count=0 does not error, it is silently parsed as a
property filter for a count property in a property set named query:types,
and matches nothing. Quote the keys, as the other query examples already do.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Bruno Postle
2026-09-09 20:16:07 +01:00
committed by Dion Moult
parent ba9810f459
commit 1c6362ec31
@@ -56,11 +56,13 @@ Filtering is typically used to select any IFC element or type.
"``IfcWall, Pset_WallCommon.FireRating=2HR``", "Any 2 hour fire rated wall"
"``IfcWall, Pset_WallCommon.ThermalTransmittance=""1.5""``", "Any wall with a U-value of 1.5. Note the quotes: ``1.5`` contains a ``.``, so unquoted it is a syntax error. See `Quoting values in filters`_."
"``IfcWall, IfcColumn, IfcBeam, IfcFooting, /Pset_.*Common/.LoadBearing=TRUE``", "Any load bearing structure"
"``IfcElement, /Pset_.*Common/.FireRating != NULL``", "Any element with a fire rating property"
"``IfcWall, type=WT01, location=""Level 3""``", "Any walls of wall type WT01 on level 3 (we quote Level 3 since it has a space)"
"``IfcWall, type=WT01, location=""Level 3""``", "Any walls of wall type WT01 on level 3. We quote ``Level 3`` because it contains a space, but a space is only one of several characters that force quoting - see `Quoting values in filters`_."
"``IfcElement, classification=/Pr_.*/``", "Any maintainable product according to Uniclass tables"
@@ -116,7 +118,7 @@ will search through all IfcTypeProducts and IfcProducts in the IFC project.
"Classification", "Filter", "``classification{{=}}{{value}}``", "``classification=Foo`` specifies the criteria that elements must have an IfcClassificationReference with an ``Identification`` attribute with a value of ``Foo``."
"Location", "Filter", "``location{{=}}{{value}}``", "``location=Foo`` specifies the criteria that elements must be contained directly or indirectly in a spatial element with a ``Name`` attribute with a value of ``Foo``."
"Parent", "Filter", "``parent{{=}}{{value}}``", "``parent=Foo`` specifies the criteria that elements must be a direct or indirect child in the spatial hierarchy to an element with a ``Name`` attribute with a value of ``Foo``."
"Query", "Filter", "``query:{{keys}}{{=}}{{value}}``", "``query:types.count=0`` specifies the criteria that elements must have zero type occurrences. The query keys corresponds to the syntax used in the `Getting element values`_ section"
"Query", "Filter", "``query:{{keys}}{{=}}{{value}}``", "``query:""types.count""=0`` specifies the criteria that elements must have zero type occurrences. The query keys corresponds to the syntax used in the `Getting element values`_ section. Note that the keys are quoted: they usually contain a ``.``, which an unquoted string may not. See `Quoting values in filters`_."
.. note::
@@ -149,9 +151,49 @@ three ways you can do so:
:header: "Value Type", "Example", "Description"
"Quoted string", "``""foo \""bar\"" baz""``", "The value must be in double quotes. The value may contain spaces, symbols, and other characters. If you need to use a double quote, you can escape it with a backslash. This is the safest, most general way to specify a value."
"Unquoted string", "``foobarbaz``", "For convenience, if you have a simple value which contains no spaces or special characters, you are free to specify it as an unquoted string."
"Unquoted string", "``foobarbaz``", "For convenience, if your value contains none of the characters listed under `Quoting values in filters`_ below, you are free to specify it as an unquoted string."
"Regex string", "``/foo.*baz/``", "You may specify a Python-compatible regex pattern delimited by forward slashes. You can learn more about regular expressions from `Beginners Regex tutorial <https://regexone.com/>`_ and `Online Regex testing website <https://regex101.com/>`_."
Quoting values in filters
~~~~~~~~~~~~~~~~~~~~~~~~~
An unquoted ``{{pset}}``, ``{{prop}}``, ``{{keys}}``, or ``{{value}}`` may not
contain any of the following characters:
.. code-block::
, . = > < * ! and whitespace
If yours contains one of them, quote it. Every one of them except ``,`` is a
syntax error when left unquoted. The ``,`` is the more dangerous case, because
it does not error: it is read as the separator between two filters. So
``Name=Foo,IfcWall`` does not look for the literal name ``Foo,IfcWall``, it
quietly means "named ``Foo`` **and** an ``IfcWall``". Write
``Name="Foo,IfcWall"`` to match the literal value.
The ``.`` is the one most likely to catch you out. It separates a property set
from a property, so it cannot also appear in an unquoted value, and that makes
every decimal number a syntax error unless it is quoted:
.. code-block::
Pset_WallCommon.ThermalTransmittance=1.5 # syntax error
Pset_WallCommon.ThermalTransmittance="1.5" # correct
Whole numbers are unaffected, which is why ``FireRating=2HR`` and
``ThermalTransmittance>1`` are fine unquoted while ``ThermalTransmittance>1.5``
is not. Quoting a number does not turn the check into a text comparison -
``>``, ``>=``, ``<``, and ``<=`` still compare numerically, so
``ThermalTransmittance>"0.9"`` does match a value of ``1.5``.
.. note::
Query keys obey this same rule, and they nearly always contain a ``.``, so
in practice they always need quoting. Write ``query:"types.count"=0``.
Written as ``query:types.count=0`` it does not error, it is silently read
as a *property* filter looking for a ``count`` property inside a property
set named ``query:types``, which is not what you asked for.
Getting element values
----------------------
@@ -235,9 +277,31 @@ do so:
:header: "Value Type", "Example", "Description"
"Quoted string", "``""foo \""bar\"" baz""``", "The value must be in double quotes. The value may contain spaces, symbols, and other characters. If you need to use a double quote, you can escape it with a backslash. This is the safest, most general way to specify a value."
"Unquoted string", "``foobarbaz``", "For convenience, if you have a simple value which contains no spaces or special characters, you are free to specify it as an unquoted string."
"Unquoted string", "``foobarbaz``", "For convenience, if your key contains none of the characters listed under `Quoting keys in value queries`_ below, you are free to specify it as an unquoted string."
"Regex string", "``/foo.*baz/``", "You may specify a Python-compatible regex pattern delimited by forward slashes. You can learn more about regular expressions from `Beginners Regex tutorial <https://regexone.com/>`_ and `Online Regex testing website <https://regex101.com/>`_."
Quoting keys in value queries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The characters that need quoting here are not the same set as in
`Quoting values in filters`_. An unquoted key may not contain any of:
.. code-block::
. = / and whitespace
All four are a syntax error when left unquoted, so there is no silent
misreading to worry about in this position. The ``.`` is the key separator and
the ``/`` delimits a regex, so a property set or property whose own name
contains either - or a space - has to be quoted:
.. code-block::
"Fire Rating Data".FireRating
The remaining characters that force quoting in a filter - ``,``, ``>``, ``<``,
``*``, and ``!`` - are accepted unquoted here.
Formatting
----------