tfussell / xlnt

:bar_chart: Cross-platform user-friendly xlsx library for C++11+
Other
1.5k stars 423 forks source link

xlm:parsing "custom-properties" #96

Closed sukoi26 closed 7 years ago

sukoi26 commented 7 years ago

in first, i have a xml string as

Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties" Target="docProps/custom.xml"/>
</Relationships>

give error to decode .

In second, the file custom.xml cannot be parsed. "Properties expected"

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
-<Properties xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes" xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties">
-<property name="AppVersion" pid="2" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}">
<vt:lpwstr>14.0300</vt:lpwstr>
</property>
-<property name="DocSecurity" pid="3" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}">
<vt:i4>0</vt:i4>
</property>
-<property name="HyperlinksChanged" pid="4" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}">
<vt:bool>0</vt:bool>
</property>
-<property name="LinksUpToDate" pid="5" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}">
<vt:bool>0</vt:bool>
</property>
-<property name="ScaleCrop" pid="6" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}">
<vt:bool>0</vt:bool>
</property>
-<property name="ShareDoc" pid="7" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}">
<vt:bool>0</vt:bool>
</property>
</Properties>
tfussell commented 7 years ago

This is my first time actually seeing custom properties. This one should be easy enough to fix. You manage to find all of the bugs in my library!

engineer84 commented 7 years ago

I have the same problem: xlnt:: error : unhandled case http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties

tfussell commented 7 years ago

Thanks @engineer84. I'll be looking into this soon.

tfussell commented 7 years ago

This is fixed on the latest commit to master. Do note that the custom properties are not round-tripped yet. They won't cause an error when reading a file that contains them and can be accessed via xlnt::workbook::custom_property.

engineer84 commented 7 years ago

That rocks! Everything is working now. Much appreciated.

engineer84 commented 7 years ago

Perfect! No round trip needed by me. Thanks so much. Works now

On Jan 2, 2017, at 5:28 PM, Thomas Fussell notifications@github.com<mailto:notifications@github.com> wrote:

This is fixed on the latest commit to master. Do note that the custom properties are not round-tripped yet. They won't cause an error when reading a file that contains them and can be accessed via xlnt::workbook::custom_property.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/tfussell/xlnt/issues/96#issuecomment-270031947, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AKh0Bfwb66nqJ2pM_5sEWqzR-gHkb-_Nks5rOYgNgaJpZM4LNg_H.

sukoi26 commented 7 years ago

Sorry, please reopen as

1 0x00007ffff798c26e in xml::parser::next_expect (this=0x7fffffffc7b0, e=xml::parser::end_element, ns="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", n="i4"

the parser check only the vt:lpwstr but ECMA said "

" in the code missing a switch case of choice element vt: for name
sukoi26 commented 7 years ago

the code involved, i suggest to remove the if then on variant_child_element cause each name need an element but some case as link to analyse

void xlsx_consumer::read_properties(const path &part, const xml::qname &root)
{
    static const auto &xmlns_vt = constants::namespace_("vt");

    auto content_type = manifest().content_type(part);

    std::unordered_map<std::string, std::string> properties;
    expect_start_element(root, xml::content::complex);

    while (in_element(root))
    {
        auto property_element = expect_start_element(xml::content::mixed);

        if (property_element.name() != "property")
        {
            properties[property_element.name()] = read_text();
        }
        else
        {
            auto property_name = parser().attribute("name");
            auto variant_child_element = expect_start_element(xml::content::simple);

            **if (variant_child_element == xml::qname(xmlns_vt, "lpwstr"))
            {
                properties[property_name] = read_text();
            }**

            expect_end_element(variant_child_element);
        }

        skip_remaining_content(property_element);
        expect_end_element(property_element);
    }

    expect_end_element(root);

    if (content_type == "application/vnd.openxmlformats-officedocument.custom-properties+xml")
    {
        for (const auto &prop : properties)
        {
            target_.custom_property(prop.first, prop.second);
        }
    }
}
tfussell commented 7 years ago

I thought I could get away with only implementing vt:lpwstr. I'll at least come up with a way for the properties you've attached to be parsed correctly. Thanks for coming up with a code solution too.

sukoi26 commented 7 years ago

after the revision https://github.com/tfussell/xlnt/commit/7e391d9ef2668317f3abfbc7f19a1d5973e0af88 i note major improvement in read/save.

concern save: still pid count nok (stay = 2) missing variant value

<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
  <property name="ScaleCrop" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2">
    <vt:lpwstr></vt:lpwstr>
  </property>
  <property name="AppVersion" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2">
    <vt:lpwstr>15.0300</vt:lpwstr>
  </property>
  <property name="ShareDoc" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2">
    <vt:lpwstr></vt:lpwstr>
  </property>
  <property name="DocSecurity" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2">0</property>
  <property name="HyperlinksChanged" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2">
    <vt:lpwstr></vt:lpwstr>
  </property>
  <property name="LinksUpToDate" fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2">
    <vt:lpwstr></vt:lpwstr>
  </property>
</Properties>

i f i read the saved file EXCEL warm

Part removed: part /xl/styles.xml  error XML. (Styles) Error Line 54, column 27
Record repaired: Information cell in part /xl/worksheets/sheet1.xml 
sukoi26 commented 7 years ago

Patch for the bug bool (any bool is i4 writing) consummer.cpp

        if (element == qn("vt", "i4"))
        {
            value = variant(std::stoi(text));
        }
    ++    if (element == qn("vt", "bool"))
    ++   {
    ++      bool bvalue = std::stoi(text);
     ++     value = variant(bvalue);
     ++ }
sukoi26 commented 7 years ago

no so good a bool could be a number or a text

 if (element == qn("vt", "bool"))
        {
         // bool could be "0" or "false"
        bool bvalue;
        if (text[0] == '0' or text[0] == 'f' or text[0]=='F') bvalue = false;
        else bvalue = true; 
        value = variant(bvalue);
        }
sukoi26 commented 7 years ago

closed