Hi,
I am trying to read an XML file with compas, I can read such structure in C++ or Rhino .NET.
Is there a special way that XML files must be prepared for your reader?
The error message:
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 1
Code and XML file are below:
the xml reader in compas is mostly meant for internal use with the other file readers (perhaps we should not advertise it in the public api).
python has very good support for xml already built-in with the xml
package. i suggest you use that one directly…
Thank you, I will apply directly the python xml.
Hi @petrasvestartas! I would be interested in figuring out why your file fails to be read, could you please attach it here, or email it to me directly and I’ll test?
Thanks!
Dear @gonzalocasas ,
This is the xml I am using
Currently I am reading this file in C++ like this incase needed:
inline bool read_xml(joint& joint, int type = 0) {
std::string name = "";//custom
switch (type) {
case(12):
case(0):
name = "ss_e_ip_9";
break;
case(11):
case(1):
name = "ss_e_op_9";
break;
case(20):
case(2):
name = "ts_e_p_9";
break;
case(30):
case(3):
name = "cr_c_ip_9";
break;
case(40):
case(4):
name = "tt_e_p_9";
break;
case(50):
case(5):
name = "ss_e_r_9";
break;
}
joint.name = name;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Check if XML file exists, path_and_file_for_joints is a global path
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP File path %s ", path_and_file_for_joints.c_str());
printf("\nCPP Joint Type %i %s ", type, name.c_str());
#endif
if (!exists_test3(path_and_file_for_joints)) {
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP File does not exist %s ", path_and_file_for_joints.c_str());
#endif
std::ofstream myfile;
myfile.open("C:\\Users\\petra\\AppData\\Roaming\\Grasshopper\\Libraries\\compas_wood\\example.txt");
myfile << "Do not Exist\n";
myfile << path_and_file_for_joints;
myfile.close();
return false;
}
else {
//std::ofstream myfile;
//myfile.open("C:\\Users\\petra\\AppData\\Roaming\\Grasshopper\\Libraries\\compas_wood\\example.txt");
//myfile << "Exists\n";
//myfile << path_and_file_for_joints;
//myfile.close();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Read XML
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
boost::property_tree::ptree tree;
boost::property_tree::xml_parser::read_xml(path_and_file_for_joints, tree);
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP tree size %zi ", tree.size());
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Get Property to find the right joint parameters and keys of XML file properties
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Traverse property tree example
std::string xml_joint_name = "custom_joints." + name;
std::array<std::string, 7> keys = { "m0", "m1","f0","f1", "m_boolean_type","f_boolean_type","properties" };
std::array<int, 6> array_id = { 0,1,0,1,0,1 };
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Get properties from XML and add to joint
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
try {
for (boost::property_tree::ptree::value_type& v : tree.get_child(xml_joint_name)) {
//printf("\nCPP %s", v.first.c_str());
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP %s", v.first.c_str());
#endif
for (int i = 0; i < 4; i++) {
if (v.first == keys[i]) {
//std::cout << v.first << "\n";
CGAL_Polyline polyline;
for (boost::property_tree::ptree::value_type& point : v.second) {
double x = point.second.get<double>("x");
double y = point.second.get<double>("y");
double z = point.second.get<double>("z");
polyline.emplace_back(x, y, z);
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP Vector %.17g %.17g %.17g", x, y, z);
#endif
}
//printf("\n");
//CGAL_Debug(polyline.size());
//Assign to array
switch (i) {
case(0):
joint.m[0].emplace_back(polyline);
//printf("\nCPP joint.m[0].emplace_back(polyline)");
break;
case(1):
joint.m[1].emplace_back(polyline);
//printf("\nCPP joint.m[1].emplace_back(polyline)");
break;
case(2):
joint.f[0].emplace_back(polyline);
//printf("\nCPP joint.f[0].emplace_back(polyline)");
break;
case(3):
joint.f[1].emplace_back(polyline);
//printf("\nCPP joint.f[1].emplace_back(polyline)");
break;
}
}
}
for (int i = 4; i < 6; i++) {
std::vector<char> boolean_type;
if (v.first == keys[i]) {
//std::cout << v.first << "\n";
for (boost::property_tree::ptree::value_type& index : v.second) {
char id = index.second.get_value<char>();
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP id %c ", id);
#endif
if (i == 4) {
joint.m_boolean_type.emplace_back(id);
//emplace to female joint.m_boolean_type
}
else {
joint.f_boolean_type.emplace_back(id);
//emplace to female joint.f_boolean_type
}
}
//Assign to array
}
}
if (v.first == keys[6]) {
std::vector<double> properties;
for (boost::property_tree::ptree::value_type& index : v.second) {
double parameter = index.second.get_value<double>();
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP id %f ", parameter);
#endif
properties.emplace_back(parameter);
}
if (properties.size() > 0) {
joint.unit_scale = properties[0] > 0;
}
//Assign to array
}
}
}
catch (std::exception& e) {
#ifdef DEBUG_JOINERY_LIBRARY
printf("\nCPP Wrong property ");
#endif
std::ofstream myfile;
myfile.open("C:\\Users\\petra\\AppData\\Roaming\\Grasshopper\\Libraries\\compas_wood\\example.txt");
myfile << "Wrong Property\n";
myfile.close();
return false;
}
//std::ofstream myfile;
//myfile.open("C:\\Users\\petra\\AppData\\Roaming\\Grasshopper\\Libraries\\compas_wood\\example.txt");
//myfile << "Good Result\n";
//myfile.close();
//CGAL_Debug(joint.f[0].size(), joint.f[1].size(), joint.f_boolean_type.size());
//CGAL_Debug(joint.m[0].size(), joint.m[1].size(), joint.m_boolean_type.size());
return true;
}
}
Ah, that’s an easy one. The file has a BOM.
There are two possible quick solutions:
- Open your XML file with VS Code, then click
UTF-8
on the bottom right, select Save with encoding
:
And select UTF-8
from the list (the option that does NOT say “with BOM”)
This will get rid of the BOM and parsing will work.
- Another possible workaround is to open the file and handle the decoding yourself, eg:
with open(filename, 'r') as f:
content = f.read().decode('utf')
xml = XML.from_string(content)
This will force the content to be utf-8 decoded which in turn with get rid of that annoying extra byte (BOM) on first position and make the XML parsing work.
I suggest one of the two options because adding BOM support to compas is a rather low prio task, so don’t expect it soon.
Cheers
1 Like
Thank you for the help:)
I did not know about the BOM before and that there are different encoding options for xml files.
1 Like