
Mon, 09/22/2025 - 15:45
Hi everyone,
I’m new to the OCCT community, so this is probably a dumb question, but I’m running into a puzzling issue.
We have a C++ script that generates an XML/XCAF document from a STEP file. When we read back this XML in C++, everything works fine — the document has 1 free shape as expected.
However, when I try to read the same XML file in PythonOCC, I get 0 free shapes. Here’s a minimal example of what I’m doing in Python:
from OCC.Core.TDocStd import TDocStd_Document,TDocStd_Application
from OCC.Core.XCAFApp import XCAFApp_Application
from OCC.Core.XCAFDoc import XCAFDoc_DocumentTool
from OCC.Core.XmlXCAFDrivers import xmlxcafdrivers
from OCC.Core.PCDM import PCDM_ReaderStatus
from OCC.Core.TDF import TDF_LabelSequence, TDF_Label
# ----------- Input data (XML file w/metadata) --------------
INP_FILE = "C:/Users/vnoailles/Downloads/test.xml"
# ------------------------------------------------------------
# Create XDE application and register drivers
app = XCAFApp_Application.GetApplication()
xmlxcafdrivers.DefineFormat(app)
# Initialize document and open file
doc = TDocStd_Document("XmlXCAF")
status = app.Open(INP_FILE,doc)
# Report status
print("Open status:", status, "OK is", PCDM_ReaderStatus.PCDM_RS_OK)
if status != PCDM_ReaderStatus.PCDM_RS_OK:
raise RuntimeError(f"Failed to open XML document, status = {status}")
# Access XDE tools
shape_tool = XCAFDoc_DocumentTool.ShapeTool(doc.Main())
# Get root labels
labels = TDF_LabelSequence() #Initialize TDF labels
shape_tool.GetFreeShapes(labels) #Populate labels with FreeShapes
print(f"OCAF Document - Free shapes found: {labels.Length()}")
if labels.Length() == 0:
raise RuntimeError("No free shapes found in STEP file")
And here is the code I have in C++:
// corrected_xcaf_io.cpp
#include <STEPCAFControl_Reader.hxx>
#include <TDocStd_Application.hxx>
#include <TDocStd_Document.hxx>
#include <XCAFApp_Application.hxx>
#include <XmlXCAFDrivers.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <PCDM.hxx>
#include <TDF_LabelSequence.hxx>
#include <TDataStd_Name.hxx>
#include <TCollection_ExtendedString.hxx>
#include <Quantity_Color.hxx>
#include <IFSelect_ReturnStatus.hxx>
#include <TCollection_AsciiString.hxx>
#include <iostream>
#include <stdexcept>
#define STEP_PATH "C:/Users/vnoailles/Downloads/testStep/base_wall_mount_vc.stp"
#define XML_PATH "C:/Users/vnoailles/Downloads/test.xml"
void writeXML()
{
// init app and XML driver
Handle(XCAFApp_Application) app = XCAFApp_Application::GetApplication();
XmlXCAFDrivers::DefineFormat(app);
// create new document (XmlXCAF)
Handle(TDocStd_Document) doc;
app->NewDocument("XmlXCAF", doc);
// read STEP
STEPCAFControl_Reader reader;
IFSelect_ReturnStatus rf = reader.ReadFile(STEP_PATH);
if (rf != IFSelect_RetDone) {
throw std::runtime_error("STEP read failed (IFSelect_ReturnStatus != IFSelect_RetDone)");
}
// transfer STEP into OCAF/XCAF document
if (!reader.Transfer(doc)) {
throw std::runtime_error("STEPCAFControl_Reader::Transfer() failed");
}
std::cout << "Imported STEP into XCAF document.\n";
// tools
TDF_Label mainLabel = doc->Main();
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
Handle(XCAFDoc_ColorTool) colorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
// get free shapes
TDF_LabelSequence freeShapes;
shapeTool->GetFreeShapes(freeShapes);
std::cout << "Free shapes found: " << freeShapes.Length() << "\n";
if (freeShapes.Length() > 0) {
TDF_Label shapeLabel = freeShapes.Value(1);
// set a color (example)
Quantity_Color red(1.0, 0.0, 0.0, Quantity_TOC_RGB);
colorTool->SetColor(shapeLabel, red, XCAFDoc_ColorGen);
// set a name using the TDataStd_Name attribute (correct approach)
TCollection_ExtendedString nameExt("PrismShape");
TDataStd_Name::Set(shapeLabel, nameExt);
std::cout << "Set name 'PrismShape' and color on first free shape.\n";
}
// save document as XML
PCDM_StoreStatus s = app->SaveAs(doc, TCollection_ExtendedString(XML_PATH));
if (s != PCDM_StoreStatus::PCDM_SS_OK) {
throw std::runtime_error("Failed to save XCAF document to XML (SaveAs returned non-OK).");
}
std::cout << "Saved XCAF document to: " << XML_PATH << "\n";
app->Close(doc);
}
void readXML()
{
Handle(XCAFApp_Application) app = XCAFApp_Application::GetApplication();
XmlXCAFDrivers::DefineFormat(app);
// create and open doc
Handle(TDocStd_Document) doc = new TDocStd_Document("XmlXCAF");
PCDM_ReaderStatus rstatus = app->Open(XML_PATH, doc);
if (rstatus != PCDM_ReaderStatus::PCDM_RS_OK) {
throw std::runtime_error(std::string("Error: cannot open document. Status = ") + std::to_string((int)rstatus));
}
std::cout << "OCAF document loaded successfully.\n";
TDF_Label mainLabel = doc->Main();
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
Handle(XCAFDoc_ColorTool) colorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
TDF_LabelSequence freeShapes;
shapeTool->GetFreeShapes(freeShapes);
std::cout << "OCAF Document - Free shapes found: " << freeShapes.Length() << "\n";
if (freeShapes.Length() > 0) {
TDF_Label shapeLabel = freeShapes.Value(1);
// read the name attribute (if present)
Handle(TDataStd_Name) nameAttr;
if (shapeLabel.FindAttribute(TDataStd_Name::GetID(), nameAttr)) {
TCollection_ExtendedString ext = nameAttr->Get();
// convert to ASCII for printing (simple approach)
TCollection_AsciiString ascii(ext);
std::cout << "Shape name: " << ascii.ToCString() << "\n";
}
else {
std::cout << "No TDataStd_Name attribute attached to the label.\n";
}
}
app->Close(doc);
}
int main()
{
try {
writeXML();
readXML();
}
catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
return 1;
}
return 0;
}
Also here is the C++ output :
Imported STEP into XCAF document.
Free shapes found: 1
Set name 'PrismShape' and color on first free shape.
Saved XCAF document to: C:/Users/vnoailles/Downloads/prism_wBCs.xml
OCAF document loaded successfully.
OCAF Document - Free shapes found: 1
Shape name: PrismShape
And here is the output on python side
Open status: 0 OK is PCDM_ReaderStatus.PCDM_RS_OK
OCAF Document - Free shapes found: 0
Traceback (most recent call last):
File "C:\Users\vnoailles\Desktop\CAD-Project-Test-Archi\FastAPI\main.py", line 34, in <module>
raise RuntimeError("No free shapes found in STEP file")
RuntimeError: No free shapes found in STEP file
You can also see the stp file used and the xml generated in attached file
Attachments: