Attribute Parser

Sort by

recency

|

484 Discussions

|

  • + 0 comments
    #include <iostream>
    #include <vector>
    #include <string>
    #include <map>
    #include <sstream>
    #include <iomanip>
    
    using namespace std;
    
    class HRMLTree
    {
    private:
        HRMLTree *m_parent = nullptr;
        string m_tag;
        map<string, string> m_attributes;
        vector<HRMLTree *> m_childs;
    
    public:
        void setTag(string tag)
        {
            m_tag = tag;
        }
        void setParent(HRMLTree *parent)
        {
            m_parent = parent;
        }
        string getTag()
        {
            return m_tag;
        }
        const vector<HRMLTree *> &getChilds()
        {
            return m_childs;
        }
        HRMLTree *getParent()
        {
            return m_parent;
        }
        void addChild(HRMLTree *tree)
        {
            m_childs.push_back(tree);
        }
        string findAttribute(const string &attribute_name)
        {
            map<string, string>::iterator it;
            if ((it = m_attributes.find(attribute_name)) == m_attributes.end())
                return "Not Found!";
    
            return it->second;
        }
        void parseHRMLTagLine(string tag_line)
        {
            tag_line = tag_line.substr(1, tag_line.size() - 2);
            string attributes = parseTag(tag_line);
            parseAttributes2(attributes);
        }
        string parseTag(const string &tag_line)
        {
            int end = tag_line.find(' ');
            if (end == string::npos)
                end = tag_line.size();
    
            string tag = tag_line.substr(0, end);
            setTag(tag);
    
            return tag_line.substr(end);
        }
        void parseAttributes2(const string &attributes)
        {
            istringstream iss(attributes);
            string attribute_name, delimiter, attribute_value;
    
            while (iss >> attribute_name >> delimiter >> quoted(attribute_value))
            {
                m_attributes[attribute_name] = attribute_value;
            }
        }
        ~HRMLTree()
        {
            for (HRMLTree *child : m_childs)
                delete child;
    
            m_childs.clear();
        }
    };
    
    string readLine()
    {
        string line;
        line.reserve(200);
        getline(cin, line);
        return line;
    }
    
    void readHRMLTree(HRMLTree *parent, uint16_t tag_lines_count)
    {
        while (tag_lines_count > 0)
        {
            string tag_line = readLine();
    
            if (tag_line[1] == '/') // is ending tag?
            {
                parent = parent->getParent();
            }
            else
            {
                HRMLTree *child = new HRMLTree;
                child->parseHRMLTagLine(tag_line);
                child->setParent(parent);
                parent->addChild(child);
                parent = child;
            }
            tag_lines_count--;
        }
    }
    
    HRMLTree *findChild(HRMLTree *parent, const string &tag)
    {
        for (HRMLTree *child : parent->getChilds())
        {
            if (child->getTag() == tag)
                return child;
        }
    
        return nullptr;
    }
    
    void printQueries(HRMLTree *parent, uint16_t query_count)
    {
        while (query_count > 0)
        {
            string query = readLine();
    
            // split attribute name and tags
            int tilde_index = query.find('~');
            string attribute_name = query.substr(tilde_index + 1);
            string tags = query.substr(0, tilde_index);
    
            // loop over tags
            HRMLTree *parent_ref = parent;
            istringstream iss(tags);
            string tag;
    
            while (getline(iss, tag, '.'))
            {
                parent_ref = findChild(parent_ref, tag);
                if (!parent_ref)
                    break;
            }
    
            // print values
            if (!parent_ref)
                cout << "Not Found!" << endl;
            else
                cout << parent_ref->findAttribute(attribute_name) << endl;
    
            query_count--;
        }
    }
    
    int main()
    {
        uint16_t tag_lines_count, query_count;
        cin >> tag_lines_count >> query_count;
        cin.ignore();
    
        HRMLTree *tree = new HRMLTree;
        readHRMLTree(tree, tag_lines_count);
        printQueries(tree, query_count);
    
        delete tree;
    }
    
  • + 0 comments

    I approached this problem by designing a custom struct with tag paths and attributes, and using a stack to handle nested tags. I wrote a detailed breakdown on GitHub if anyone wants to learn from it. Feel free to check my profile for my GitHub link.

  • + 0 comments

    It’s amazing for system programming, game development, and building high-performance applications. exchange id cricket

  • + 0 comments

    This solutions makes use of Composite to fully show the hierachy of the tags.

    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <sstream>
    #include <map>
    using namespace std;
    
    
    struct TagNode {
        string name;
        map< std::string, std::string > attributes;
        vector< TagNode* > children;
    
        ~TagNode() {
            for ( auto child : children ) {
                delete child;
            }
        }
    };
    
    
    string queryAttribute( TagNode * root, const std::string& query ) {
        istringstream iss( query );
        string path;
        getline( iss, path, '~' );
        string attribute;
        getline( iss, attribute );
    
        TagNode* current = root;
        istringstream pathIss( path );
        string tag;
        
    
        while ( getline( pathIss, tag, '.' ) ) {
            bool found = false;
            for ( auto child : current->children ) {
                if ( child->name == tag ) {
                    current = child;
                    found = true;
                    break;
                }
            }
            if ( !found ) return "Not Found!";
        }
    
        auto it = current->attributes.find( attribute );
        if ( it != current->attributes.end() ) return it->second;
        else                                   return "Not Found!";
    }
    
    
    
    int main() {
        int N, Q;
        
        cin >> N >> Q;
        string line = "";
        cin.ignore();
        vector< TagNode * > currentNode;
        TagNode * root = new TagNode;
        currentNode.push_back( root );
        
        while( N-- > 0 ) {
            string str; 
            getline( cin, str );
            
            if( str[ 1 ] != '/' ) {
                int leer = str.find( ' ' );
                if( leer == string::npos ) {
                    leer = str.size() - 1;
                }
    
                TagNode* node = new TagNode;
                node->name = str.substr( 1, leer - 1 );
                
                str = str.substr( leer + 1 );
                while( str.empty() == false ) {
                    int nameEnd = str.find( ' ' );
                    string key =  str.substr( 0, nameEnd );
                    str = str.substr( nameEnd + 4 );
                    int valueEnd   = str.find( '"' );
                    string value   = str.substr( 0, valueEnd );
                    str = str.substr( valueEnd + 2 );
                    node->attributes[ key ] = value;
                }
                
    
                currentNode.back()->children.push_back( node );
                currentNode.push_back( node );
            }
            else {
                currentNode.pop_back();
            }
        }
    
        while( Q-- > 0 ) {
            string line;
            cin >> line;
            cout << queryAttribute( root, line ) << "\n";
        }
    
        return 0;
    }
    
  • + 0 comments

    Probably no the best solution, but it works:

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    
    void ltrim(string &s) {
        s.erase(s.begin(), find_if(s.begin(), s.end(), [](unsigned char ch) {
            return !isspace(ch);
        }));
    }
    
    void delete_quotes(string &s) {
        if (s.size() >= 2 && s.front() == '"' && s.back() == '"') {
            s.erase(s.begin());
            s.pop_back();
        }
    }
    
    int main() {
           
        int n, q;
        
        cin >> n >> q;
        
        vector<string> tag_stack;
        map<string, string> attrs;
        
        cin.ignore();
        
        for (int i = 0; i < n; i++) {
            string line;
            getline(cin, line);
            
            if (line[1] != '/') {
                string tag;
                size_t position = 1; // Start from position 1 to ignore the tag opening '<'
    
                // Capture the tag name:
                while (position < line.size()) {
                    // If a space or '>' is found, the tag name is complete
                    if (line[position] == ' ' || line[position] == '>') break;
                    tag += line[position++]; // The increment is performed after the character is added
                }
    
                tag_stack.push_back(tag); // Add the tag to the stack
    
                string path = tag_stack[0];
                
                // Create the tag path:
                for (int j = 1; j < tag_stack.size(); j++) path += ("." + tag_stack[j]);
                
                // Create a substring considering only the attributes and their values
                string attributes = line.substr(position, line.length() - position - 1); // Exclude the closing '>'
                ltrim(attributes);
                
                // Assign the attributes to the path
                attrs[path] = attributes;
            } else {
                tag_stack.pop_back();
            }
        }
        
        for (int i = 0; i < q; ++i) {
            string query;
            getline(cin, query);
    
            size_t tilde = query.find('~');
            string path = query.substr(0, tilde);
            string attr = query.substr(tilde + 1);
    
            if (attrs.count(path)) {
                string tag_attrs = attrs[path];
                size_t position = tag_attrs.find(attr);
    
                if (tag_attrs.find(attr) != string::npos && (position == 0 || isspace(tag_attrs[position - 1]))) {
                    string value;
                    position += attr.length() + 3; // Skip ' = '
    
                    // Capture the value of the attribute:
                    while (position < tag_attrs.length() && tag_attrs[position] != ' ') value += tag_attrs[position++];
    
                    delete_quotes(value);
    
                    cout << value << endl;
                } else {
                    cout << "Not Found!" << endl;
                }
            } else {
                cout << "Not Found!" << endl;
            }
        }
    }