Documentation
About Archicad's documenting tools, views, model filtering, layouts, publishing, etc.

Custom classification creation

bouhmidage
Advisor

Hello,

As far asvi know, the only method to create a custom classification system is to use classification window inside Archicad, create classes one by one, number them, oh wait, if i want to reorder my classes, it will be a nightmare....

 

I tried to generate classifications by mapping an excel tible using Archicad classification map, but it does not export, Archicad xml mapping uses list of lists mapping and this is not supported by excel.

 

Antone explored this field and had some good results ??

 

Also classification from revit can't be loaded in Archicad 

 

A better classification manager should be inttoduced soon, 

AMD Ryzen 9 3900X, 32 GB RAM, RTX 3080 10 GB
Archicad 25
Windows 10 professional
https://www.behance.net/Nuance-Architects
14 REPLIES 14
stefan
Expert

I have played a bit with a Python script to convert a Revit classification file directly into an Archicad classification XML you can import. It's not perfect and needs to be tuned to the input file (e.g., how the code was set up into fields - but also how to get children inside the right parent), but this one brings you a huge step in the right direction.

 

import copy
import sys
import os
import xml.etree.ElementTree as ET
import datetime

def parse_line(line):
    # Each other line has
    # Code Tab Code:description Tab Number Tab Tab
    # split with tabs
    fields = line.strip().split("\t")
    code = fields[0]
    # print(" -- Code = " + fields[0])
    fields2 = fields[1].strip().split(":")
    description = fields2[1]
    # print(" -- Description = " + fields2[1])
    return (fields[0], fields2[1])


def parse_rvt_assembly(filename):
    print(filename)
    now = datetime.datetime.now()
    # Prepare XML output
    # root = ET.fromstring('<?xml version="1.0" encoding="utf-8" standalone="no"?>')
    BuildingInformation = ET.Element('BuildingInformation')
    Classification = ET.SubElement(BuildingInformation, 'Classification')
    System = ET.SubElement(Classification, 'System')
    Name = ET.SubElement(System, 'Name')
    EditionVersion = ET.SubElement(System, 'EditionVersion')
    EditionDate = ET.SubElement(System, 'EditionDate')
    Year = ET.SubElement(EditionDate, 'Year')
    Year.text = str(now.year)
    Month = ET.SubElement(EditionDate, 'Month')
    Month.text = str(now.month)
    Day = ET.SubElement(EditionDate, 'Day')
    Day.text = str(now.day)
    Description = ET.SubElement(System, 'Description')
    Source = ET.SubElement(System, 'Source')
    Items = ET.SubElement(System, 'Items')

    # Make a dictionary of parents, by chopping of the last field of the ID
    parents = dict()

    # Coming from Revit, it's UTF-16, Little-Endian, CRLF
    with open(filename, 'r', encoding='utf-16-le') as infile:
        # First line = * TAB Title TAB Number TAB TAB
        firstline = infile.readline()
        fields = firstline.strip().split("\t")
        Name.text = fields[1]
        EditionVersion.text = '0.1'

        # parse the items from the Third line
        for line in infile.readlines()[3:]:
            # Ignore all other lines which start with *, # or !
            if line.startswith('#') or line.startswith('*') or line.startswith('!') or line.startswith('@'):
                print("Skipped " + line)
            else:
                print(line.strip())
                fields = parse_line(line)
                # fields[0] = code
                # fields[1] = description

                # And then find out the parent, by splitting the "ID" on dots
                CodeFields = fields[0].split(".")
                # if the code ends with a dot, remove the (empty) last item too
                if (CodeFields[-1] == ''):
                    CodeFields.pop()
                if len(CodeFields) > 0:
                    foundParent = False
                    ParentFields = copy.deepcopy(CodeFields) # otherwise we pop the original
                    while not foundParent:
                        ParentFields.pop()
                        if len(ParentFields) == 0:
                            foundParent = True
                            Item = ET.SubElement(Items, 'Item')
                        else:
                            parentID = ".".join(ParentFields)
                            parentID += "."
                            if parentID in parents:
                                parent = parents[parentID]
                                # add item to children
                                ParentChildren = parent.find('Children')
                                if ParentChildren is None:
                                    ParentChildren = ET.SubElement(parent, 'Children')
                                Item = ET.SubElement(ParentChildren, 'Item')
                                foundParent = True

                # finish
                Code = ET.SubElement(Item, 'ID')
                ItemName = ET.SubElement(Item, 'Name')
                ItemName.text = fields[1]
                ItemChildren = ET.SubElement(Item, 'Children')
                Code.text = fields[0]
                ItemDescription = ET.SubElement(Item, 'Description')
                ItemDescription.text = fields[1]

                # Add to the dictionary
                parents[fields[0]] = Item


    with open("output.xml", "wb") as f:
        # convert xml data to byte object before writing
        b_xml = ET.tostring(BuildingInformation)
        f.write(b_xml)


if __name__ == '__main__':
    filename = sys.argv[1]
    if os.path.isfile(filename):
        parse_rvt_assembly(filename)

 

When applied to my input file, the result looks like the following fragment (after I applied XML-tidy script in a text editor):

 

<?xml version="1.0" encoding="utf-8"?>
<BuildingInformation>
	<Classification>
		<System>
			<Name>RG904 v. 2014 - Regie Der Gebouwen</Name>
			<EditionVersion>0.1</EditionVersion>
			<EditionDate>
				<Year>2021</Year>
				<Month>9</Month>
				<Day>10</Day>
			</EditionDate>
			<Description/>
			<Source/>
			<Items>
				<Item>
					<ID>01.01.</ID>
					<Name>Inrichten van de bouwplaats</Name>
					<Children>
						<Item>
							<ID>01.01.10.</ID>
							<Name>Voorlopige omheining</Name>
							<Children/>
							<Description>Voorlopige omheining</Description>
						</Item>
						<Item>
							<ID>01.01.11.</ID>
							<Name>Voorlopige omheining in overeenstemming met de gemeentelijke voorschriften</Name>
							<Children/>
							<Description>Voorlopige omheining in overeenstemming met de gemeentelijke voorschriften</Description>
						</Item>

 

And this gets imported nicely in Archicad. But your mileage may vary.

 

--- stefan boeykens --- bim-expert-architect-engineer-musician ---
Archicad27/Revit2023/Rhino8/Unity/Solibri/Zoom
MBP2023:14"M2MAX/Sonoma+Win11
Archicad-user since 1998
my Archicad Book
bouhmidage
Advisor

Hello again 

I'm not famliar with coding language, but, if your code is strong enough to be an "international translaor" it would be a great tool, 

I'm still working on the excel file, more accurate for me, trying to solve the problem i mentioned before 

AMD Ryzen 9 3900X, 32 GB RAM, RTX 3080 10 GB
Archicad 25
Windows 10 professional
https://www.behance.net/Nuance-Architects
bouhmidage
Advisor

Hello again ! 

I did this, but it didn't work, i followed all the formulas, 

I even opened in notepad++ a classification generated from Archicad to see how it's structured, 

I created the SAME structure in excel, ( i checked similaritie using a formula ) 

when i copy from excel to notepad ++ , save, and reimport in Archicad, it says corrupted xml file, 

Test.png

AMD Ryzen 9 3900X, 32 GB RAM, RTX 3080 10 GB
Archicad 25
Windows 10 professional
https://www.behance.net/Nuance-Architects
stefan
Expert

I can only recommend to work in smaller parts. E.g. one item first and see if that works. I had issues with encoding (accented letters etc...), with missing attributes (name? description?). So start simple and work from there. Unfortunately the importer is not that helpful with its error message.

--- stefan boeykens --- bim-expert-architect-engineer-musician ---
Archicad27/Revit2023/Rhino8/Unity/Solibri/Zoom
MBP2023:14"M2MAX/Sonoma+Win11
Archicad-user since 1998
my Archicad Book
bouhmidage
Advisor

That's what i did, i worlked on smart parts, and thn , i made it larger with more sublevels, each time i find random results, 

a good classification generator inside Archicad would be helpful 

AMD Ryzen 9 3900X, 32 GB RAM, RTX 3080 10 GB
Archicad 25
Windows 10 professional
https://www.behance.net/Nuance-Architects