XML Reader structure of a file

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:

  1. 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.

  1. 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. :slight_smile:

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