【问题标题】:A simple C XML parser一个简单的 C XML 解析器
【发布时间】:2010-05-17 19:09:04
【问题描述】:

我需要从 C 程序中读取 XML 格式的文档并从中提取元素及其值。比如下面的代码:

<user name="Mark">
    <param name="Age" value="21"/>
    <param name="Country" value="NL"/>
</user>

我需要提取:name = MarkAge = 21Country = NL

直到今天,我一直在手动进行这种解析,这很痛苦。

我不关心文件是“正确的 XML”还是其他所有,我不关心 DTD 或其他标准 XML 要求。我只需要读取和解析这些值。

有没有人知道除了 lib eXpat 之外的库可以执行此操作或代码执行此操作?

谢谢!

【问题讨论】:

  • 在询问库时,您可能希望提及您的平台,因为库可以是特定于平台的。

标签: c xml


【解决方案1】:

【讨论】:

  • 谢谢,我已经检查过了,1)我花了很长时间才明白他们想要我做什么(为了使它工作)和 2)它抱怨我没有 DTD 和我的文件格式不正确。所以,不是一个好的解决方案。
  • 它不应该需要 DTD,但它确实需要 XML 格式正确——即开始/结束标签匹配并且没有非法字符并且有一个并且只有根元素。如果您的输入格式不正确,也许您应该修复它。如果您不要求输入是格式良好的 XML,而只是类似于 xml 的内容,那么您可以轻松编写自己的解析器:只需搜索“”字符将其分成几部分,然后解析每一块。 XML 解析器的很多复杂性是因为它必须将任何通用 XML 解析为特定的内部模型。
  • 不要。永远不要尝试编写自己的 XML 解析器,也永远不要尝试使用字符串拆分器解析 XML。您将遇到编码和转义问题。您将遇到互操作性问题。您将遇到安全问题。例如,像这里建议的许多其他 cmets 一样,为您的平台使用经过验证、测试和建立的库之一 expat 或 libxml2。
【解决方案2】:

Expat 解析器是我遇到的最好的 - 我在 C++ 代码中使用它而不是各种 C++ 解析器 - 但它是用 C 编写的。非常易于使用并嵌入到您的应用程序中。所以我不明白你为什么在你的问题中说:

(除了 lib eXpat)

你有反对意见吗?

【讨论】:

  • 确实,考虑到给定的要求,我肯定会选择外籍人士。我能想到的在这种情况下不使用它的唯一原因是,如果发帖人无法从 SAX 事件中创建数据结构,因此需要 DOM?
  • 不,我没有反对它,事实上我正在另一个项目中使用它,但是它很大,而且我需要的东西比我需要的更复杂。所以,正如我在问题中明确指出的那样,我不会将 expat 作为解决方案
  • @Jessica 您必须对“大”这个词有自己的私有定义——Expat 与您将获得的 XML 解析器差不多。具体来说,它比 Mini-XML 小。
  • 在哪里可以了解在 C windows 平台中使用 expat 进行 xml 解析?
【解决方案3】:

Mini-XML 怎么样?它是轻量级的,可与 gcc 一起使用,兼容 ANSI-C...

http://www.minixml.org/index.php

根据文档,搜索特定节点很简单:

/* Find the first "a" element */
    node = mxmlFindElement(tree, tree, "a",
                           NULL, NULL,
                           MXML_DESCEND);

一旦获得节点,就可以根据自己的要求对其进行操作。

【讨论】:

  • 谢谢,我已经发布了这个(见我自己对问题的回答)
【解决方案4】:

如果 C++ 没问题,那么你可以试试TinyXML。我已经用了几年了,效果很好。

【讨论】:

    【解决方案5】:

    Mini-XML 看起来很有前景

    http://www.minixml.org/

    【讨论】:

      【解决方案6】:

      您可以考虑miniML-Parser,这是一个简单而小巧的 C 语言 XML 解析器库。

      • 与其他 XML 解析器不同,它非常易于使用。您只需调用一个 API 即可解析您的 XML 数据。
      • 它是一个验证解析器。它验证 XML 数据的语法并提取 XML 数据的内容。

      为了从 XML 数据中解析和提取内容,您需要向解析器提供一些信息。例如 XML 元素名称、其子元素、属性、内容类型等。解析器使用 xs_element_t 结构来保存 XML 数据的所有这些属性

      在您的示例中,您有 2 个 XML 元素“用户”和“参数”。 user 是根元素,param 是子元素。属性“名称”和“值”保存内容。为了提取这些内容,您需要指定内容类型和目标地址来存储内容。

      您的 XML 数据的 xs_element_t 示例。

      const xs_element_t user_root =
      {
          .Name.String = "user",                 //!< name of XML element
          .Name.Length = 4,                      //!< Length of name
          
          .Attribute_Quantity = 1,               //!< Number of attributes of this element
          .Attribute          = attributes,      //!< Address of structure containing attributes
      
          .Child_Quantity = 1,                   //!< Number of child elements
          .Child          = &param_element,      //!< Address of structure holding child elements
      };
      
      const xs_element_t param_element =
      {
          .Name.String = "param",                //!< name of XML element
          .Name.Length = 5,                      //!< Length of name
      
          .Attribute_Quantity = 2,               //!< Number of attributes of this element
          .Attribute          = attributes,      //!< Address of structure containing attributes    
      };
      
      //! Holds properties of attributes
      const xs_attribute_t attributes[] =
      {
          [0].Name.String = "name",           //!< Name of XML attribute
          [0].Name.Length = 4,                //!< Length of attribute name
      
          [0].Target.Type = EN_STATIC,        //!< Target address type is static.
          [0].Target.Address = &name,         //!< Target address offset from the parent target address
          [0].Content.Type   = EN_STRING,     //!< Content type is string.             
      
          [1].Name.String = "value",          //!< Name of XML attribute
          [1].Name.Length = 4,                //!< Length of attribute name
      
          [1].Target.Type = EN_STATIC,        //!< Target address type is static.
          [1].Target.Address = &value,        //!< Target address offset from the parent target address
          [1].Content.Type   = EN_STRING,     //!< Content type is string.             
      };
      

      注意:以上结构不完整。为了使示例简单,我省略了一些结构成员。

      要解析 xml 数据,然后调用 parse_xml() 并传递 user_root(根元素)的地址和 XML 数据。

      parse_xml(&user_root, xml_data, NULL);
      

      您还可以在 xs_element_t 结构中注册一个回调函数,以便在解析器在解析过程中遇到元素/标签时获取回调。

      更多详情请参考https://github.com/kiishor/miniML-Parser

      披露:我是这个 miniML-Parser 的作者

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-18
        • 2012-09-06
        • 1970-01-01
        • 2010-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多