通过 sql server xml 数据类型提升与 xml 之间的序列化异常
好吧,这是我的问题。
我有一个 boost 对象,它通过序列化创建 xml 字符串,这工作得很好。
使用 boost 版本 1.38,
我获取该 xml 字符串并将其保存到 sql server 数据库表中,转换为 xml 数据类型,这也可以正常工作。
然后,我从数据库表中检索 xml 字符串,但格式与插入时相比略有变化,基本上空白值已被短标记,从 到 < code>
下面是之前和之后的 xml 示例。
之前
<grid class_id="0" tracking_level="0" version="0">
<name>test_table</name>
<columns class_id="1" tracking_level="0" version="0">
<count>2</count>
<item_version>0</item_version>
<item class_id="2" tracking_level="1" version="0" object_id="_0">
<label>AAAA</label>
<data>xxxx</data>
</item>
<item class_id_reference="2" object_id="_1">
<label>BBBB</label>
<data></data>
</item>
</columns>
</grid>
之后
<grid class_id="0" tracking_level="0" version="0">
<name>test_table</name>
<columns class_id="1" tracking_level="0" version="0">
<count>2</count>
<item_version>0</item_version>
<item class_id="2" tracking_level="1" version="0" object_id="_0">
<label>AAAA</label>
<data>xxxx</data>
</item>
<item class_id_reference="2" object_id="_1">
<label>BBBB</label>
<data /> <!-- NOW SHORT TAGGED -->
</item>
</columns>
</grid>
这也很好,完全可以接受,并不意外。
当我获取这个 xml 字符串并尝试将 xml 序列化回 boost 对象时,问题就出现了,当它遇到 xml 字符串中的短标记时,它会抛出异常。
我遇到了这个问题,不知道如何解决这个问题,并且在网上找不到任何关于这个问题的参考,所以任何帮助将不胜感激。
:)
这是我的代码,它应该编译没有任何问题,你只需要填写数据库部分的空白:
grid.hpp
////////////////////////////////////////////////////////////////
// grid boost serialization object
//
#pragma once
#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/version.hpp>
/////////////////////////////////////////////////////////////
// Column
//
namespace sdcm
{
class Column
{
public:
// every serializable class needs a constructor
Column()
{
}
Column(const std::string& _label, const std::string& _data)
: label(_label),
data(_data)
{
}
private:
friend class boost::serialization::access;
friend std::ostream & operator<<(std::ostream &os, const Column &col);
std::string label;
std::string data;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */)
{
ar & BOOST_SERIALIZATION_NVP(label)
& BOOST_SERIALIZATION_NVP(data)
;
}
};
class Grid
{
public:
// every serializable class needs a constructor
Grid()
{
}
Grid(const std::string& _name)
: name(_name)
{
}
void append(Column* col)
{
columns.insert(columns.end(), col);
}
private:
friend class boost::serialization::access;
friend std::ostream & operator<<(std::ostream &os, const Grid &grid);
std::string name;
typedef Column* GRID_COLUMNS;
std::list<GRID_COLUMNS> columns;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(name)
& BOOST_SERIALIZATION_NVP(columns);
}
};
} // end namespace
main.cpp
// boost_test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <sstream>
#include <iostream>
#include <string>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include "grid.hpp"
std::string get_grid_as_xml_str(sdcm::Grid& grid)
{
std::ostringstream xml ;
unsigned int flags = boost::archive::no_header
//| boost::archive::no_codecvt
//| boost::archive::no_xml_tag_checking
//| boost::archive::no_tracking
;
boost::archive::xml_oarchive oa(xml, flags);
oa << BOOST_SERIALIZATION_NVP(grid);
return xml.str();
}
void restore_grid_from_xml_str(sdcm::Grid& grid, const std::string& xml_str)
{
std::istringstream xml(xml_str);
unsigned int flags = boost::archive::no_header
//| boost::archive::no_codecvt
//| boost::archive::no_xml_tag_checking
//| boost::archive::no_tracking
;
boost::archive::xml_iarchive ia(xml, flags);
ia >> BOOST_SERIALIZATION_NVP(grid);
}
int _tmain(int argc, _TCHAR* argv[])
{
// create grid obj with cols
sdcm::Grid grid("MY GRID");
grid.append(new sdcm::Column("AAAA", "xxxx")) ;
grid.append(new sdcm::Column("BBBB", "")) ;
// get grid as xml string
std::string xml = get_grid_as_xml_str(grid) ;
// Assume xml is saved to SQL Server DB table in XML datatype,
// and the data has be retrived is a shorted tag format used
// where blank values are present in tags
// make a new grid
sdcm::Grid new_grid;
restore_grid_from_xml_str(new_grid, xml);
return 0;
}
Ok, here's my problem.
I have a boost object which creates xml string via serialization, this works just fine.
Using boost version 1.38
I take that xml string and save it to a sql server database table into an xml datatype, this also work fine.
I then retrieve my xml string from the database table, but the format has changed slightly from when it was inserted, basically blank values have been short tagged, from <data></data>
to <data/>
Here's an example of the xml before and after.
Before
<grid class_id="0" tracking_level="0" version="0">
<name>test_table</name>
<columns class_id="1" tracking_level="0" version="0">
<count>2</count>
<item_version>0</item_version>
<item class_id="2" tracking_level="1" version="0" object_id="_0">
<label>AAAA</label>
<data>xxxx</data>
</item>
<item class_id_reference="2" object_id="_1">
<label>BBBB</label>
<data></data>
</item>
</columns>
</grid>
After
<grid class_id="0" tracking_level="0" version="0">
<name>test_table</name>
<columns class_id="1" tracking_level="0" version="0">
<count>2</count>
<item_version>0</item_version>
<item class_id="2" tracking_level="1" version="0" object_id="_0">
<label>AAAA</label>
<data>xxxx</data>
</item>
<item class_id_reference="2" object_id="_1">
<label>BBBB</label>
<data /> <!-- NOW SHORT TAGGED -->
</item>
</columns>
</grid>
This is also fine and perfectly acceptable and not unexpected.
The problem comes when I take this xml string and try to serialize the xml back into the boost objects, it throws and exception when it comes across the short tagged tag in the xml string.
I've hit a brick wall with this and don't know how to fix the problem, and can't find any reference to this problem on the web, so any help would be greatly appreciated.
:)
Here's my code, it should compile without any issues, you just need to fill in the blanks for the db part:
grid.hpp
////////////////////////////////////////////////////////////////
// grid boost serialization object
//
#pragma once
#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/version.hpp>
/////////////////////////////////////////////////////////////
// Column
//
namespace sdcm
{
class Column
{
public:
// every serializable class needs a constructor
Column()
{
}
Column(const std::string& _label, const std::string& _data)
: label(_label),
data(_data)
{
}
private:
friend class boost::serialization::access;
friend std::ostream & operator<<(std::ostream &os, const Column &col);
std::string label;
std::string data;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */)
{
ar & BOOST_SERIALIZATION_NVP(label)
& BOOST_SERIALIZATION_NVP(data)
;
}
};
class Grid
{
public:
// every serializable class needs a constructor
Grid()
{
}
Grid(const std::string& _name)
: name(_name)
{
}
void append(Column* col)
{
columns.insert(columns.end(), col);
}
private:
friend class boost::serialization::access;
friend std::ostream & operator<<(std::ostream &os, const Grid &grid);
std::string name;
typedef Column* GRID_COLUMNS;
std::list<GRID_COLUMNS> columns;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(name)
& BOOST_SERIALIZATION_NVP(columns);
}
};
} // end namespace
main.cpp
// boost_test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <sstream>
#include <iostream>
#include <string>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include "grid.hpp"
std::string get_grid_as_xml_str(sdcm::Grid& grid)
{
std::ostringstream xml ;
unsigned int flags = boost::archive::no_header
//| boost::archive::no_codecvt
//| boost::archive::no_xml_tag_checking
//| boost::archive::no_tracking
;
boost::archive::xml_oarchive oa(xml, flags);
oa << BOOST_SERIALIZATION_NVP(grid);
return xml.str();
}
void restore_grid_from_xml_str(sdcm::Grid& grid, const std::string& xml_str)
{
std::istringstream xml(xml_str);
unsigned int flags = boost::archive::no_header
//| boost::archive::no_codecvt
//| boost::archive::no_xml_tag_checking
//| boost::archive::no_tracking
;
boost::archive::xml_iarchive ia(xml, flags);
ia >> BOOST_SERIALIZATION_NVP(grid);
}
int _tmain(int argc, _TCHAR* argv[])
{
// create grid obj with cols
sdcm::Grid grid("MY GRID");
grid.append(new sdcm::Column("AAAA", "xxxx")) ;
grid.append(new sdcm::Column("BBBB", "")) ;
// get grid as xml string
std::string xml = get_grid_as_xml_str(grid) ;
// Assume xml is saved to SQL Server DB table in XML datatype,
// and the data has be retrived is a shorted tag format used
// where blank values are present in tags
// make a new grid
sdcm::Grid new_grid;
restore_grid_from_xml_str(new_grid, xml);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然有点晚了,但我确实收到了 boost 的回复电子邮件。
是的,这确实是一个错误,但他们不会修复它。
如果我们有兴趣,请回复:
Bit late, but I did get a reply email from boost.
Yes it is somewhat of a bug, but they are not going to fix it.
Here the reply if our interested: