mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Expand wildcard attributes in IfcCsv export (#3424)
Exporting with a "*" attribute (or "Pset_Name.*") emitted a literal "*" column filled with the null placeholder instead of expanding: the get_wildcard_attributes helper had no callers after a refactor dropped the expansion step. Wire the expansion back in: before the per-element loop, export() now calls expand_wildcard_attributes, which passes through non-wildcard queries unchanged, expands a bare "*" to every direct attribute of the exported elements (new get_element_attributes helper), and expands "Pset_Name.*" / "Qto_Name.*" via the existing get_wildcard_attributes helper. Expanded columns that duplicate an existing one (e.g. GlobalId or an explicit Name) are skipped. Verified headless: exporting an IfcWall with ["Name","*"] now yields real attribute columns with values (W1, MyWall, T1, ...) instead of a literal "*", "Pset_WallCommon.*" expands to that pset's properties, and an explicit named-attribute export is unchanged. Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -105,6 +105,9 @@ class IfcCsv:
|
||||
attributes.insert(0, "GlobalId")
|
||||
headers.insert(0, "GlobalId")
|
||||
|
||||
elements = list(elements)
|
||||
attributes, headers = self.expand_wildcard_attributes(attributes, headers, elements)
|
||||
|
||||
for element in elements:
|
||||
result = []
|
||||
|
||||
@@ -384,6 +387,44 @@ class IfcCsv:
|
||||
self.dataframe = pd.DataFrame(self.results, columns=self.headers)
|
||||
return self.dataframe
|
||||
|
||||
def expand_wildcard_attributes(self, attributes, headers, elements):
|
||||
"""Expand any attribute containing ``*`` into concrete attribute names.
|
||||
|
||||
A bare ``*`` expands to every direct attribute of the exported elements.
|
||||
A ``Pset_Name.*`` (or ``Qto_Name.*``) query expands to every property of
|
||||
that named property set / quantity set, using ``get_wildcard_attributes``.
|
||||
Attributes without a ``*`` are passed through unchanged so explicit
|
||||
named queries keep their position and any custom header.
|
||||
"""
|
||||
expanded_attributes = []
|
||||
expanded_headers = []
|
||||
for attribute, header in zip(attributes, headers):
|
||||
if "*" not in attribute:
|
||||
expanded_attributes.append(attribute)
|
||||
expanded_headers.append(header)
|
||||
continue
|
||||
if attribute == "*":
|
||||
expansions = self.get_element_attributes(elements)
|
||||
else:
|
||||
expansions = self.get_wildcard_attributes(attribute)
|
||||
for expanded in expansions:
|
||||
if expanded in expanded_attributes:
|
||||
continue # Avoid duplicate columns (e.g. GlobalId).
|
||||
expanded_attributes.append(expanded)
|
||||
# Expanded columns fall back to the attribute name as header.
|
||||
expanded_headers.append(None)
|
||||
return expanded_attributes, expanded_headers
|
||||
|
||||
def get_element_attributes(self, elements):
|
||||
results = []
|
||||
for element in elements:
|
||||
for name in element.get_info(recursive=False):
|
||||
if name in ("id", "type"):
|
||||
continue
|
||||
if name not in results:
|
||||
results.append(name)
|
||||
return results
|
||||
|
||||
def get_wildcard_attributes(self, attribute):
|
||||
results = set()
|
||||
pset_qto_name = attribute.split(".", 1)[0]
|
||||
|
||||
Reference in New Issue
Block a user