xBimTeam / XbimExchange

XbimExchange contains several COBie schemas and serialisation functions as well as the Model Validation library adopted by theNBS digital toolkit.
https://xbimteam.github.io/
Other
46 stars 42 forks source link

COBieLite Namespace #56

Open simiii opened 3 years ago

simiii commented 3 years ago

I am converting an IFC-File into COBieLite like this:

                var cobieLiteHelper = new CoBieLiteHelper(ifcStore, null, null);
                var facilities = cobieLiteHelper.GetFacilities();

                using (TextWriter writer = File.CreateText("model.xml"))
                {
                    foreach (var facilityType in facilities) {
                        CoBieLiteHelper.WriteXml(writer, facilityType);
                    }
                }

the generated XML-File looks like the following using the core-namespace for everything except the facility.

<?xml version="1.0" encoding="utf-8"?>
<cobielite:Facility xmlns:core="http://docs.buildingsmartalliance.org/nbims03/cobie/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" core:externalEntityName="IfcBuilding" core:externalID="11000" core:externalSystemName="IFC text editor" xmlns:cobielite="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite">
  <core:FacilityName>01.1.A</core:FacilityName>
  <core:ProjectAssignment core:externalEntityName="IfcProject" core:externalID="100" core:externalSystemName="IFC text editor">
    <core:ProjectName>FM-A-01</core:ProjectName>
  </core:ProjectAssignment>
  <core:SiteAssignment core:externalEntityName="IfcSite" core:externalID="10010" core:externalSystemName="IFC text editor">
    <core:SiteName>FM Test Site</core:SiteName>
    <core:SiteDescription>Site object for testing Basic FM Handover</core:SiteDescription>
  </core:SiteAssignment>
  <core:FacilityDefaultLinearUnit>meters</core:FacilityDefaultLinearUnit>
  <core:FacilityDefaultAreaUnit>square meters</core:FacilityDefaultAreaUnit>
  <core:FacilityDefaultVolumeUnit>cubic meters</core:FacilityDefaultVolumeUnit>
  <core:FacilityDescription>Building object for testing Basic FM Handover</core:FacilityDescription>
  <core:Floors>
    <core:Floor core:externalEntityName="IfcBuildingStorey" core:externalID="20100" core:externalSystemName="IFC text editor">
      <core:FloorName>A.-1</core:FloorName>
      <core:FloorDescription>Kellergeschoss</core:FloorDescription>
      <core:FloorElevationValue>
        <core:DecimalValue>-3.2</core:DecimalValue>
      </core:FloorElevationValue>
      <core:FloorHeightValue />
    </core:Floor>
  </core:Floors>
</cobielite:Facility>

From the example clinik-file from https://www.nibs.org/page/bimc_cobielite I recognized that they use the cobielite-namespace instead of the core-namespace. Can I change the behaviour of the CoBieLiteHelper to use the cobielite-namespace? Is it a bug not using the cobielite-namespace as it provides more attributes for the elements in the xml?

Example: Can deserialize Attribute Value

<?xml version="1.0" encoding="utf-8"?>
<cobielite:Facility xmlns:core="http://docs.buildingsmartalliance.org/nbims03/cobie/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" core:externalEntityName="IfcBuilding" core:externalID="11000" core:externalSystemName="IFC text editor" xmlns:cobielite="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite">
  <core:FacilityName>01.1.A</core:FacilityName>
  <core:ProjectAssignment core:externalEntityName="IfcProject" core:externalID="100" core:externalSystemName="IFC text editor">
    <core:ProjectName>FM-A-01</core:ProjectName>
  </core:ProjectAssignment>
  <core:SiteAssignment core:externalEntityName="IfcSite" core:externalID="10010" core:externalSystemName="IFC text editor">
    <core:SiteName>FM Test Site</core:SiteName>
    <core:SiteDescription>Site object for testing Basic FM Handover</core:SiteDescription>
  </core:SiteAssignment>
  <core:FacilityDefaultLinearUnit>meters</core:FacilityDefaultLinearUnit>
  <core:FacilityDefaultAreaUnit>square meters</core:FacilityDefaultAreaUnit>
  <core:FacilityDefaultVolumeUnit>cubic meters</core:FacilityDefaultVolumeUnit>
  <core:FacilityDescription>Building object for testing Basic FM Handover</core:FacilityDescription>
  <core:FacilityAttributes>
    <cobielite:Attribute core:propertySetName="Pset_BuildingCommon">
      <core:AttributeName>YearOfConstruction</core:AttributeName>
      <core:AttributeCategory>Submitted</core:AttributeCategory>
      <core:AttributeValue>
        <core:AttributeStringValue>
          <core:StringValue>2002</core:StringValue>
        </core:AttributeStringValue>
      </core:AttributeValue>
    </cobielite:Attribute>
    <cobielite:Attribute core:propertySetName="Pset_BuildingCommon">
      <core:AttributeName>IsLandmarked</core:AttributeName>
      <core:AttributeCategory>Submitted</core:AttributeCategory>
      <core:AttributeValue>
        <core:AttributeBooleanValue />
      </core:AttributeValue>
    </cobielite:Attribute>
  </core:FacilityAttributes>
</cobielite:Facility>

Example: Cannot deserialize Attribute Value:

<?xml version="1.0" encoding="utf-8"?>
<cobielite:Facility xmlns:core="http://docs.buildingsmartalliance.org/nbims03/cobie/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" core:externalEntityName="IfcBuilding" core:externalID="11000" core:externalSystemName="IFC text editor" xmlns:cobielite="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite">
  <core:FacilityName>01.1.A</core:FacilityName>
  <core:ProjectAssignment core:externalEntityName="IfcProject" core:externalID="100" core:externalSystemName="IFC text editor">
    <core:ProjectName>FM-A-01</core:ProjectName>
  </core:ProjectAssignment>
  <core:SiteAssignment core:externalEntityName="IfcSite" core:externalID="10010" core:externalSystemName="IFC text editor">
    <core:SiteName>FM Test Site</core:SiteName>
    <core:SiteDescription>Site object for testing Basic FM Handover</core:SiteDescription>
  </core:SiteAssignment>
  <core:FacilityDefaultLinearUnit>meters</core:FacilityDefaultLinearUnit>
  <core:FacilityDefaultAreaUnit>square meters</core:FacilityDefaultAreaUnit>
  <core:FacilityDefaultVolumeUnit>cubic meters</core:FacilityDefaultVolumeUnit>
  <core:FacilityDescription>Building object for testing Basic FM Handover</core:FacilityDescription>
  <core:FacilityAttributes>
    <core:Attribute core:propertySetName="Pset_BuildingCommon">
      <core:AttributeName>YearOfConstruction</core:AttributeName>
      <core:AttributeCategory>Submitted</core:AttributeCategory>
      <core:AttributeValue>
        <core:AttributeStringValue>
          <core:StringValue>2002</core:StringValue>
        </core:AttributeStringValue>
      </core:AttributeValue>
    </core:Attribute>
    <core:Attribute core:propertySetName="Pset_BuildingCommon">
      <core:AttributeName>IsLandmarked</core:AttributeName>
      <core:AttributeCategory>Submitted</core:AttributeCategory>
      <core:AttributeValue>
        <core:AttributeBooleanValue />
      </core:AttributeValue>
    </core:Attribute>
  </core:FacilityAttributes>
</cobielite:Facility>

Thanks for your help, Simon

andyward commented 3 years ago

Simon,

From what I can tell CobieLite defines its schema across 2 separate XSDs: core.xsd and cobielite.xsd, with the later referencing items in the former.

In your examples above, I think the only difference is that xbim is being explicit with the namespace; whereas the example COBieLite at https://portal.nibs.org/files/wl/?id=EAyFiAEke4wwmojNiVSo2GMwPZJYJdWy is setting core as the default namespace, and so omits core: from the elements

e.g. This is the start of the sample file

<?xml version="1.0" encoding="UTF-8"?>
<cobielite:Facility xmlns:cobielite="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite" 
xmlns="http://docs.buildingsmartalliance.org/nbims03/cobie/core" 
xmlns:core="http://docs.buildingsmartalliance.org/nbims03/cobie/core" 
core:externalEntityName="IfcBuilding" core:externalID="3eM8WbY_59RR5TDWry5aRU" core:externalSystemName="Autodesk Revit Architecture 2011" xsi:schemaLocation="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite cobielite.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <FacilityName>PN 0001</FacilityName>
  <FacilityCategory>11-13 24 14: Clinic</FacilityCategory>

... where FacilityName etc are implicitly in the core namespace.

Regarding the issue:

Looks to me that cobieLite:Attribute is correct. core.Attribute is the abstract super type, which is probably why it can't be deserialised.

What's the origin of the last CobieLite file in your issue? it looks wrong... Change the core.Attribute to cobielite:Attribute and it should work.

simiii commented 3 years ago

Hi thanks for your answer!

the last file in my issue is generated with xbim. If I change the namespace from core:Attribute to cobielite:Attribute it works fine as you suggest.

In my first example (xml also generated with xbim) the core:Floor should also be cobielite:Floor as the FloorElevationValue only exists for cobielite (see xsd) and not in core.

`

<xs:complexType name="FloorType">
    <xs:annotation>
        <xs:documentation>A minimum of one COBie.Floor record is required for all COBie deliverables containing spatial information.</xs:documentation>
    </xs:annotation>
    <xs:complexContent>
        <xs:extension base="core:FloorType">
            <xs:sequence>
                <xs:element ref="core:FloorCategory" minOccurs="0"/>
                <xs:element ref="core:FloorDescription" minOccurs="0"/>
                <xs:element ref="core:FloorElevationValue" minOccurs="0"/>
                <xs:element ref="core:FloorHeightValue" minOccurs="0"/>
                <xs:element ref="core:Spaces" minOccurs="0"/>
                <xs:element ref="core:FloorAttributes" minOccurs="0"/>
                <xs:element ref="core:FloorDocuments" minOccurs="0"/>
                <xs:element ref="core:FloorIssues" minOccurs="0"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
<xs:element name="Floor" type="cobielite:FloorType" substitutionGroup="core:Floor">
    <xs:annotation>
        <xs:documentation>A minimum of one COBie.Floor record is required for all COBie deliverables containing spatial information. </xs:documentation>
    </xs:annotation>
</xs:element>
<!--End Floor Related Content-->

`

I looked into your cobielite example file (Example File). There the attributes are also wrong marked with core.Attribute and not with cobieLite.Attribute.

Also interiesting: XmlSerializationCode.cs if (needType) WriteXsiType(@"AttributeTypeBase", @"http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite"); Somehow it seems to be possible to enable the correct namespace declaration.

andyward commented 3 years ago

Might need to loop in @CBenghi here as he touched this last (6 years ago!) - I'm not sure how that XmlSerialisationCode was generated - it doesn't look like standard xsd.exe generated code.

@simiii Can you describe what the actual issue is, for you and which part of your process is failing. Just to help test any fix. If you feel like digging in and putting a PR together as well that would be great. Apart from updating/PRs, I've not really been that involved in this codebase. I believe it came out of the NBS BIM Toolkit project

CBenghi commented 3 years ago

Hi all,

I can't recall having touched anything to do with the namespaces. @Andy Ward andy.ward@xbim.net, if you have had a look at the repository, can you point me in the commit in question?

On Wed, 16 Dec 2020 at 10:39, Andy Ward notifications@github.com wrote:

Might need to loop in @CBenghi https://github.com/CBenghi here as he touched this last (6 years ago!) - I'm not sure how that XmlSerialisationCode was generated - it doesn't look like standard xsd.exe generated code.

@simiii https://github.com/simiii Can you describe what the actual issue is, for you and which part of your process is failing. Just to help test any fix. If you feel like digging in and putting a PR together as well that would be great. Apart from updating/PRs, I've not really been that involved in this codebase. I believe it came out of the NBS BIM Toolkit project

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/xBimTeam/XbimExchange/issues/56#issuecomment-745993439, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJY7MJWV657JGQUO7VRFITSVB54RANCNFSM4UWZS7PA .

andyward commented 3 years ago

Hi Claudio

It was a long while ago so appreciate it may be distant memory but it was this commit https://github.com/xBimTeam/XbimExchange/commit/548301f096da56ad1f3649a69963961f2b643c18

having looked at the full history it looks like you implemented the serialisation with sgen.exe

https://github.com/xBimTeam/XbimExchange/commits/master/Xbim.COBieLite/COBieLite%20Schema/XmlSerializationCode.cs

No worries if you can't remember!

simiii commented 3 years ago

I am trying to clarify my issue. I try to read an XML generated by XBIM with Java. I generated the Java-Classes with JAXB and the cobielite and core xsd files resulting in the classes below (simplified):

org.buildingsmartalliance.docs.nbims03.cobie.core.FloorType:

public class FloorType
    extends CobieRowType
{
    @XmlElement(name = "FloorName", required = true)
    protected String floorName;
}

org.buildingsmartalliance.docs.nbims03.cobie.cobielite:FloorType

public class FloorType extends org.buildingsmartalliance.docs.nbims03.cobie.core.FloorType
{
    // other fields left for simplicity
    @XmlElement(name = "FloorAttributes", namespace = "http://docs.buildingsmartalliance.org/nbims03/cobie/core")
    protected AttributeCollectionType floorAttributes;
}

Non processable XML generated by XBIM:

<?xml version="1.0" encoding="UTF-8"?>
<cobielite:Facility xmlns:cobielite="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite"
     xmlns="http://docs.buildingsmartalliance.org/nbims03/cobie/core" 
     xmlns:core="http://docs.buildingsmartalliance.org/nbims03/cobie/core" 
     core:externalEntityName="IfcBuilding" 
     core:externalID="1TB8MXxlf6BAI7EOFPDWY9" 
     core:externalSystemName="Autodesk Revit Architecture 2012">
    <FacilityName>Test</FacilityName>
    <Floors>
        <Floor core:externalEntityName="IfcBuildingStorey" core:externalID="1TB8MXxlf6BAI7EOCcoVPF" core:externalSystemName="Autodesk Revit Architecture 2012">
            <FloorName>TestFloor</FloorName>
            <FloorCategory>FloorCategory</FloorCategory>
            <FloorDescription>FloorDescription</FloorDescription>
            <FloorElevationValue>
                <DecimalValue>12.0</DecimalValue>
            </FloorElevationValue>
            <FloorHeightValue>
                <DecimalValue>2700.0</DecimalValue>
            </FloorHeightValue>
        </Floor>
    </Floors>
</cobielite:Facility>

As you can see in the structure of the classes the attributes are only in org.buildingsmartalliance.docs.nbims03.cobie.cobielite.FloorType. If I read the XML generated by XBIM in JAVA, I only get the org.buildingsmartalliance.docs.nbims03.cobie.core.FloorType and not the subclass which results in the fact that I am unable to process the attributes in the floor.

If I manually change the namespace of the Floor to cobielite in the xml generated with xbim I can read the XML and get the subclass and therefore can read the attributes of the floor.

Processable XML generated by XBIM, manually edited:

<?xml version="1.0" encoding="UTF-8"?>
<cobielite:Facility xmlns:cobielite="http://docs.buildingsmartalliance.org/nbims03/cobie/cobielite"
     xmlns="http://docs.buildingsmartalliance.org/nbims03/cobie/core" 
     xmlns:core="http://docs.buildingsmartalliance.org/nbims03/cobie/core" 
     core:externalEntityName="IfcBuilding" 
     core:externalID="1TB8MXxlf6BAI7EOFPDWY9" 
     core:externalSystemName="Autodesk Revit Architecture 2012">
    <FacilityName>Test</FacilityName>
    <Floors>
        <cobielite:Floor core:externalEntityName="IfcBuildingStorey" core:externalID="1TB8MXxlf6BAI7EOCcoVPF" core:externalSystemName="Autodesk Revit Architecture 2012">
            <FloorName>TestFloor</FloorName>
            <FloorCategory>FloorCategory</FloorCategory>
            <FloorDescription>FloorDescription</FloorDescription>
            <FloorElevationValue>
                <DecimalValue>12.0</DecimalValue>
            </FloorElevationValue>
            <FloorHeightValue>
                <DecimalValue>2700.0</DecimalValue>
            </FloorHeightValue>
        </cobielite:Floor>
    </Floors>
</cobielite:Facility>
CBenghi commented 3 years ago

Thanks @simiii, this helps a lot, I understand the problem now. I'll look into the details tomorrow and see if I can provide a solution.

simiii commented 3 years ago

I debugged through the code and found out, that xbim is absolutely fine with reading the xml with the core-namespace. image

I created a test for reading the official example from nibs.com - the test fails as it is unable to read floors with cobielite-namespace.

        [TestMethod]
        public void CanReadSerialisedXmlWithCoreNamespace()
        {
            try
            {

                FacilityType facilityType1 = CoBieLiteHelper.ReadXml(@"Facility1.xml");
                Assert.AreEqual(4, facilityType1.Floors.LongCount());

            }
            catch (Exception ex)
            {
                while (ex.InnerException != null)
                {
                    Debug.WriteLine(ex.Message);
                    ex = ex.InnerException;
                }
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

        [TestMethod]
        public void CanReadSerialisedXmlWithCobieLiteNamespace()
        {
            try
            {
                FacilityType facilityType2 = CoBieLiteHelper.ReadXml(@"Facility2.xml");
                Assert.AreEqual(5, facilityType2.Floors.LongCount());

            }
            catch (Exception ex)
            {
                while (ex.InnerException != null)
                {
                    Debug.WriteLine(ex.Message);
                    ex = ex.InnerException;
                }
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

Should I be able to create and push a branch? I successfully cloned the repo. Currently I get the following error message:

~/git/XbimExchange (56-COBieLite-Namespace)
$ git push --set-upstream origin 56-COBieLite-Namespace
ERROR: Permission to xBimTeam/XbimExchange.git denied to simiii.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
andyward commented 3 years ago

I should create a Pull Request, which you can do from Visual Studio. But to be fair we can reproduce from your CanReadSerialisedXmlWithCobieLiteNamespace test above

simiii commented 3 years ago

In the zip file you find the Facility2.xml file. Facility2.zip