Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get the Line number in the xml file #487

Closed
Haydar1990 opened this issue Mar 18, 2022 · 3 comments
Closed

get the Line number in the xml file #487

Haydar1990 opened this issue Mar 18, 2022 · 3 comments

Comments

@Haydar1990
Copy link

Hello ,

I'm trying to parse a .xml file then with xpath read some nodes and attribute then i want to make some logical test to see if my xml file some contents error has and then i want to show the line number of the xml file with the error.

can someone help me please.

Thank you.

@cecilios
Copy link
Contributor

I think pugixml does not provides line information. So in my library (https://github.com/lenmus/lomse) I re-read the file for counting lines and creating a table relating node offset to line number. This is the code (MIT licensed):

//---------------------------------------------------------------------------------------
bool XmlParser::build_offset_data(const char* filename)
{
    //AWARE:
    // * Windows and DOS use a pair of CR (\r) and LF (\n) chars to end lines
    // * UNIX (including Linux and FreeBSD) uses only an LF char
    // * OS X also uses a single LF character
    // * The old classic Mac operating system used a single CR char
    //This code does not handle old Mac-style line breaks but it is not expected
    //to run in these old machines.
    //Also, this code does not handle tabs, that are counted as 1 char

    m_offsetData.clear();

    FILE* f = fopen(filename, "rb");
    if (!f)
        return false;

    ptrdiff_t offset = 0;

    char buffer[1024];
    size_t size;

    while ((size = fread(buffer, 1, sizeof(buffer), f)) > 0)
    {
        for (size_t i = 0; i < size; ++i)
            if (buffer[i] == '\n')
                m_offsetData.push_back(offset + i);

        offset += size;
    }

    fclose(f);

    return true;
}

//---------------------------------------------------------------------------------------
std::pair<int, int> XmlParser::get_location(ptrdiff_t offset)
{
    vector<ptrdiff_t>::const_iterator it =
        std::lower_bound(m_offsetData.begin(), m_offsetData.end(), offset);
    size_t index = it - m_offsetData.begin();

    return std::make_pair(1 + index, index == 0 ? offset + 1
                                                : offset - m_offsetData[index - 1]);
}

//---------------------------------------------------------------------------------------
int XmlParser::get_line_number(XmlNode* node)
{
    ptrdiff_t offset = node->offset();
    if (!m_fOffsetDataReady && !m_filename.empty())
        m_fOffsetDataReady = build_offset_data(m_filename.c_str());

    if ( m_fOffsetDataReady)
    {
        std::pair<int, int> pos = get_location(offset);
        return pos.first;
    }
    else
        return 0;
}

@Haydar1990
Copy link
Author

I think pugixml does not provides line information. So in my library (https://github.com/lenmus/lomse) I re-read the file for counting lines and creating a table relating node offset to line number. This is the code (MIT licensed):

//---------------------------------------------------------------------------------------
bool XmlParser::build_offset_data(const char* filename)
{
    //AWARE:
    // * Windows and DOS use a pair of CR (\r) and LF (\n) chars to end lines
    // * UNIX (including Linux and FreeBSD) uses only an LF char
    // * OS X also uses a single LF character
    // * The old classic Mac operating system used a single CR char
    //This code does not handle old Mac-style line breaks but it is not expected
    //to run in these old machines.
    //Also, this code does not handle tabs, that are counted as 1 char

    m_offsetData.clear();

    FILE* f = fopen(filename, "rb");
    if (!f)
        return false;

    ptrdiff_t offset = 0;

    char buffer[1024];
    size_t size;

    while ((size = fread(buffer, 1, sizeof(buffer), f)) > 0)
    {
        for (size_t i = 0; i < size; ++i)
            if (buffer[i] == '\n')
                m_offsetData.push_back(offset + i);

        offset += size;
    }

    fclose(f);

    return true;
}

//---------------------------------------------------------------------------------------
std::pair<int, int> XmlParser::get_location(ptrdiff_t offset)
{
    vector<ptrdiff_t>::const_iterator it =
        std::lower_bound(m_offsetData.begin(), m_offsetData.end(), offset);
    size_t index = it - m_offsetData.begin();

    return std::make_pair(1 + index, index == 0 ? offset + 1
                                                : offset - m_offsetData[index - 1]);
}

//---------------------------------------------------------------------------------------
int XmlParser::get_line_number(XmlNode* node)
{
    ptrdiff_t offset = node->offset();
    if (!m_fOffsetDataReady && !m_filename.empty())
        m_fOffsetDataReady = build_offset_data(m_filename.c_str());

    if ( m_fOffsetDataReady)
    {
        std::pair<int, int> pos = get_location(offset);
        return pos.first;
    }
    else
        return 0;
}

Thank you i'll try it.

@zeux
Copy link
Owner

zeux commented Apr 17, 2022

Also see #12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants