mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 06:58:56 +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")
|
attributes.insert(0, "GlobalId")
|
||||||
headers.insert(0, "GlobalId")
|
headers.insert(0, "GlobalId")
|
||||||
|
|
||||||
|
elements = list(elements)
|
||||||
|
attributes, headers = self.expand_wildcard_attributes(attributes, headers, elements)
|
||||||
|
|
||||||
for element in elements:
|
for element in elements:
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
@@ -384,6 +387,44 @@ class IfcCsv:
|
|||||||
self.dataframe = pd.DataFrame(self.results, columns=self.headers)
|
self.dataframe = pd.DataFrame(self.results, columns=self.headers)
|
||||||
return self.dataframe
|
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):
|
def get_wildcard_attributes(self, attribute):
|
||||||
results = set()
|
results = set()
|
||||||
pset_qto_name = attribute.split(".", 1)[0]
|
pset_qto_name = attribute.split(".", 1)[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user