zoukankan      html  css  js  c++  java
  • c++语言 xml数据绑定技术简介

    The C++ Source
    An Introduction to XML Data Binding in C++
    by Boris Kolpackov
    May 4, 2007

    原文:http://www.artima.com/cppsource/xml_data_binding.html

    一个c++应用程序需要处理 xml 格式的数据,一般的不外乎有两种存取 xml 的API:文档对象模型(Document Object Model,dom)或者 xml 简单 API。(SAX)。DOM 将xml描述为一个树状的数据结构,以供程序遍历和存取。SAX 是一个事件驱动的 解析的XML API。应用程序注册它感兴趣的事件--诸如元素结点、属性、文本之类的东东。当解析 xml时,会触发应用程序注册的这些事件。

    DOM 是先将整个 xml文档读入内存,然后再解析数据,而 SAX 是在解析过程中传递这些数据。


    无论使用 DOM还是 SAX,要处理大量的 xml 数据都非易事。毕竟,DOM 和 sax 都是 xml 结构,和对元素、属性、文本的操作,在内存中的表达。程序员不得不写大量的代码,将xml编码翻译为程序可使用的逻辑。例如,下面是一个简单的xml文档,它描述了一个人。


    <person>

      <name>John Doe</name>

      <gender>male</gender>

      <age>32</age>

    </person>


    如果我们想确保这个人的年龄大于某个阀值,那么,无论是使用 DOM 还是 SAX,我们都必须先找到“年龄”这个元素,然后将文本 “32” 转换为 int 类型。这时才能做比较。通用API的另一个显著缺点是基于字串流的控制。在上面的例子中,要查找“年龄”元素,我们需要先顺序地解析 name 元素,如果元素拼写错误,那我们只有在运行时才能发现这个 bug。字串流的代码也影响了代码的可读性和可维护性。此外,通用 api 缺乏类型安全机制,因为所有的类型都表现为文本类型。例如,我们可以堂而皇之地将表示“性别”的元素和其它的任意东西做比较,而编译器不会给出任何警告。

    DOMElement* gender = ...


    if (gender->getTextContent () == "man")

    {

      ...

    }


    近年来,出现了一种处理 xml的新手段。叫做 xml 数据绑定。xml数据绑定技术的出现,得益于 xml 语意描述语言 ( xml shemas )的发展。 xml 数据绑定技术的核心思想是:将数据解析到一个对象(而不再是内存中)。这样,程序员就不需要再处理那些 xml底层操作,因为这些对象可以被程序逻辑直接识别和执行。还是拿上面的例子来说,我们不再搜索表示年龄的文本串,把它手工转成 int,而是简单地调用 person对象的 age()方法,age 方法返回的结果是一个 int 。所谓“绑定”,就是说,“对象”必须是,而是只能是用于表达xml数据块。

    对象,以及用于操作对象的相关代码--比如解析和序列化函数--是由 数据绑定工具 生成的。数据绑定工具 是一种 来自于 xml schema。 schema 是一种语法规范--规定了元素的名称、属性、内容,以及元素之间的结构关系。大多数的 数据绑定工具都使用了 W3c 的W3C XML Schema 规范。一来因为它用的比较普遍。二来因为它的良好的面向对象特性。下面一段 代码描述了我们前面的 person 文件。使用的是 w3c xml schema 规范。

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">


      <xs:simpleType name="gender_t">

        <xs:restriction base="xs:string">

          <xs:enumeration value="male"/>

          <xs:enumeration value="female"/>

        </xs:restriction>

      </xs:simpleType>


      <xs:complexType name="person_t">

        <xs:sequence>

          <xs:element name="name" type="xs:string"/>

          <xs:element name="gender" type="gender_t"/>

          <xs:element name="age" type="xs:short"/>

        </xs:sequence>

      </xs:complexType>


      <xs:element name="person" type="person_t"/>


    </xs:schema>


    即使你不熟悉 xml schema,你也能看明白上面这些代码干了些什么。gender_t 是一种枚举类型。其值有两种可能: male 或 female。 person_t 被定义为一个序列,其中嵌套了 name, gender, age 元素。注意:术语“序列”,在xml schema 的意思是:in 元素按指定的顺序出现。a particular order as opposed to appearing multiple times. 最后,全局定义  person 指明了 结构体的根元素。关于 xml schema的更多资料,请参考 w3c规范:xml schema part0: primer。

       像其它的直接解析 xml的 api一样, xml 数据绑定也支持 内存模式和 事件驱动模式。下一节中,我们将对比  xml 数据绑定技术和 dom 及  sax 的性能表现。本例中使用的 DOM 和 SAX 例子是基于 Apache 的一款C++ 开源 XML 解析器 Xerces。为了简单起见,不对数据做类型识别。


    内存式的 xml 绑定。

    In-Memory XML Data Binding

    Based on an XML schema, a data binding compiler generates C++ classes that represent the given vocabulary as a tree-like in-memory data structure as well as parsing and serialization functions. The parsing functions are responsible for creating the in-memory representation from an XML instance while the serialization functions save the in-memory representation back to XML. For the schema presented in the introduction, a data binding compiler could generate the following code:

    利用 xml schema,数据绑定工具生成了 c++ 类。这些类把 xml数据表现内存中的树状结构的数据。和一些解析、序列化的函数。解析函数负责从xml实例中抽取数据并表达为内存对象,而序列化函数则把内存对象还原为 xml。根据前面所给的 schema,数据绑定工具会生成下面的代码:

    class gender_t

    {

    public:

      enum value {male, female};


      gender_t (value);

      operator value () const;


    private:

      ...

    };


    class person_t

    {

    public:

      person_t (const string& name,

                gender_t gender,

                short age);


      // name

      //

      string& name ();

      const string& name () const;

      void name (const string&);


      // gender

      //

      gender_t& gender ();

      gender_t gender () const;

      void gender (gender_t);


      // age

      //

      short& age ();

      short age () const;

      void age (short);


    private:

        ...

    };


    std::auto_ptr<person_t> person (std::istream&);

    void person (std::ostream&, const person_t&);

    对比代码和 xml schema声明,可以看出 schema 编译工具将 schema 类型映射为c++ 中的类,将本地元素映射为一组操作,将全局元素映射为一组解析和序列化的函数。

    下面,我们将深入观察三个普通的 xml 处理任务。使用 dom和  xml 数据绑定。这三个任务是:访问xml数据,修改现有的数据,创建新数据。通过这些试验,我们将证实 xml数据绑定比较于  dom 的优越性。

    下面的代码使用数据绑定技术来读取 xml 文件中保存的某人的信息,如果此人的姓名大于30,则打印其姓名。简单起见,没有考虑错误处理。

    ifstream ifs ("person.xml");

    auto_ptr<person_t> p = person (ifs);


    if (p->age () > 30)

      cerr << p->name () << endl;

    上面的例子简单明了。一旦xml文件读到内存中,代码便不再依赖 xml,代码和程序中的其它的对象模型配合得天衣无缝。 同时要注意 c++ class表现的数据是静态的。

    下面的代码使用 dom 来完成相同的任务。


    ifstream ifs ("person.xml");

    DOMDocument* doc = read_dom (ifs);

    DOMElement* p = doc->getDocumentElement ();


    string name;

    short age;


    for (DOMNode* n = p->getFirstChild ();

         n != 0;

         n = n->getNextSibling ())

    {

      if (n->getNodeType () != DOMNode::ELEMENT_NODE)

        continue;


      string el_name = n->getNodeName ();

      DOMNode* text = n->getFirstChild ();


      if (el_name == "name")

      {

        name = text->getNodeValue ();

      }

      else if (el_name == "age")

      {

        istringstream iss (text->getNodeValue ());

        iss >> age;

      }

    }


    if (age > 30)

      cerr << name  << endl;


    doc->release ();






        







  • 相关阅读:
    Oracle面试题目及解答
    java -jar Incompatible argument to function
    plsql 查询到别的用户下面的表
    redis数据类型[string 、list 、 set 、sorted set 、hash]
    redis-cli 常用命令
    js判断浏览器,包括Edge浏览器
    HTMl5的sessionStorage和localStorage
    JS实现密码加密
    sprintf.js
    js-crc32
  • 原文地址:https://www.cnblogs.com/diylab/p/1338034.html
Copyright © 2011-2022 走看看