Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ libxml2sax解析器-提取文本节点_C++_Xml_Sax_Libxml2_Saxparser - Fatal编程技术网

C++ libxml2sax解析器-提取文本节点

C++ libxml2sax解析器-提取文本节点,c++,xml,sax,libxml2,saxparser,C++,Xml,Sax,Libxml2,Saxparser,我想从xml输入中提取文本节点的值。我从web上获得了以下代码,因为libxml的官方文档中有许多断开的链接,sax解析器就是其中之一。请帮助我获取文本节点的值。在StartElements中,当我试图查找文本节点时,得到NULL。谢谢你的帮助 我的xml如下所示: <a> <b> <c> text values </c> </b> </a> #include <stdio.h> #in

我想从xml输入中提取文本节点的值。我从web上获得了以下代码,因为libxml的官方文档中有许多断开的链接,sax解析器就是其中之一。请帮助我获取文本节点的值。在StartElements中,当我试图查找文本节点时,得到NULL。谢谢你的帮助

我的xml如下所示:

<a>
   <b>
      <c> text values </c>
   </b>
</a>
#include <stdio.h>
#include <assert.h>
#include <memory.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <string>


class ParseFSM
{
public:
   /** SAX2 callback when an element start has been detected by the parser. It provides the namespace informations for the element, as well as the new namespace declarations on the element.
      ctx:  the user data (XML parser context)
      localname:  the local name of the element
      prefix:  the element namespace prefix if available
      URI:  the element namespace name if available
      nb_namespaces: number of namespace definitions on that node
      namespaces: pointer to the array of prefix/URI pairs namespace definitions
      nb_attributes: the number of attributes on that node
      nb_defaulted:  the number of defaulted attributes. The defaulted ones are at the end of the array
      attributes: pointer to the array of (localname/prefix/URI/value/end) attribute values.
      **/
  static void startElementNs (void *ctx,
                  const xmlChar * localname,
                  const xmlChar * prefix,
                  const xmlChar * URI,
                  int nb_namespaces,
                  const xmlChar ** namespaces,
                  int nb_attributes,
                  int nb_defaulted, const xmlChar ** attributes)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    printf ("startElementNs: name = '%s' prefix = '%s' uri = (%p)'%s'\n", localname, prefix, URI, URI);
    for (int indexNamespace = 0; indexNamespace < nb_namespaces; ++indexNamespace)
      {
        const xmlChar *prefix = namespaces[indexNamespace * 2];
        const xmlChar *nsURI = namespaces[indexNamespace * 2 + 1];
        printf ("  namespace: name='%s' uri=(%p)'%s'\n", prefix, nsURI, nsURI);
      }
    unsigned int index = 0;
    for (int indexAttribute = 0; indexAttribute < nb_attributes; ++indexAttribute, index += 5)
      {
        const xmlChar *localname = attributes[index];
        const xmlChar *prefix = attributes[index + 1];
        const xmlChar *nsURI = attributes[index + 2];
        const xmlChar *valueBegin = attributes[index + 3];
        const xmlChar *valueEnd = attributes[index + 4];
        std::string value ((const char *) valueBegin, (const char *) valueEnd);
        printf ("  %sattribute: localname='%s', prefix='%s', uri=(%p)'%s', value='%s'\n", indexAttribute >= (nb_attributes - nb_defaulted) ? "defaulted " : "", localname, prefix, nsURI, nsURI, value.c_str ());
      }
  }
   /** SAX2 callback when an element end has been detected by the parser. It provides the namespace informations for the element.
      ctx:  the user data (XML parser context)
      localname:  the local name of the element
      prefix:  the element namespace prefix if available
      URI:  the element namespace name if available
      **/
  static void endElementNs (void *ctx,
                const xmlChar * localname,
                const xmlChar * prefix, const xmlChar * URI)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    printf ("endElementNs: name = '%s' prefix = '%s' uri = '%s'\n", localname,
        prefix, URI);
  }
   /** Display and format an error messages, callback.
      ctx:  an XML parser context
      msg:  the message to display/transmit
      ...:  extra parameters for the message display
      */
  static void error (void *ctx, const char *msg, ...)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    va_list args;
    va_start (args, msg);
    vprintf (msg, args);
    va_end (args);
  }

   /** Display and format a warning messages, callback.
      ctx:  an XML parser context
      msg:  the message to display/transmit
      ...:  extra parameters for the message display
      */
  static void warning (void *ctx, const char *msg, ...)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    va_list args;
    va_start (args, msg);
    vprintf (msg, args);
    va_end (args);
  }
};
int
main (int argc, const char *argv[])
{
  std::string xmlIn = "<a><b><c> text values </c> </b> </a>"
  /*
   * this initialize the library and check potential ABI mismatches
   * between the version it was compiled for and the actual shared
   * library used.
   */
  LIBXML_TEST_VERSION xmlSAXHandler saxHandler; // See http://xmlsoft.org/html/libxml-tree.html#xmlSAXHandler
  memset (&saxHandler, 0, sizeof (saxHandler));
  // Using xmlSAXVersion( &saxHandler, 2 ) generate crash as it sets plenty of other pointers...
  saxHandler.initialized = XML_SAX2_MAGIC;  // so we do this to force parsing as SAX2.
  saxHandler.startElementNs = &ParseFSM::startElementNs;
  saxHandler.endElementNs = &ParseFSM::endElementNs;
  saxHandler.warning = &ParseFSM::warning;
  saxHandler.error = &ParseFSM::error;

  ParseFSM fsm;
  int result =
    xmlSAXUserParseMemory (&saxHandler, &fsm, xmlIn.c_str (),
               int (xmlIn.length ()));
  if (result != 0)
    {
      printf ("Failed to parse document.\n");
      return 1;
    }

  /*
   * Cleanup function for the XML library.
   */
  xmlCleanupParser ();
  /*
   * this is to debug memory for regression tests
   */
  xmlMemoryDump ();

  return 0;
}

文本值
我的代码如下所示:

<a>
   <b>
      <c> text values </c>
   </b>
</a>
#include <stdio.h>
#include <assert.h>
#include <memory.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <string>


class ParseFSM
{
public:
   /** SAX2 callback when an element start has been detected by the parser. It provides the namespace informations for the element, as well as the new namespace declarations on the element.
      ctx:  the user data (XML parser context)
      localname:  the local name of the element
      prefix:  the element namespace prefix if available
      URI:  the element namespace name if available
      nb_namespaces: number of namespace definitions on that node
      namespaces: pointer to the array of prefix/URI pairs namespace definitions
      nb_attributes: the number of attributes on that node
      nb_defaulted:  the number of defaulted attributes. The defaulted ones are at the end of the array
      attributes: pointer to the array of (localname/prefix/URI/value/end) attribute values.
      **/
  static void startElementNs (void *ctx,
                  const xmlChar * localname,
                  const xmlChar * prefix,
                  const xmlChar * URI,
                  int nb_namespaces,
                  const xmlChar ** namespaces,
                  int nb_attributes,
                  int nb_defaulted, const xmlChar ** attributes)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    printf ("startElementNs: name = '%s' prefix = '%s' uri = (%p)'%s'\n", localname, prefix, URI, URI);
    for (int indexNamespace = 0; indexNamespace < nb_namespaces; ++indexNamespace)
      {
        const xmlChar *prefix = namespaces[indexNamespace * 2];
        const xmlChar *nsURI = namespaces[indexNamespace * 2 + 1];
        printf ("  namespace: name='%s' uri=(%p)'%s'\n", prefix, nsURI, nsURI);
      }
    unsigned int index = 0;
    for (int indexAttribute = 0; indexAttribute < nb_attributes; ++indexAttribute, index += 5)
      {
        const xmlChar *localname = attributes[index];
        const xmlChar *prefix = attributes[index + 1];
        const xmlChar *nsURI = attributes[index + 2];
        const xmlChar *valueBegin = attributes[index + 3];
        const xmlChar *valueEnd = attributes[index + 4];
        std::string value ((const char *) valueBegin, (const char *) valueEnd);
        printf ("  %sattribute: localname='%s', prefix='%s', uri=(%p)'%s', value='%s'\n", indexAttribute >= (nb_attributes - nb_defaulted) ? "defaulted " : "", localname, prefix, nsURI, nsURI, value.c_str ());
      }
  }
   /** SAX2 callback when an element end has been detected by the parser. It provides the namespace informations for the element.
      ctx:  the user data (XML parser context)
      localname:  the local name of the element
      prefix:  the element namespace prefix if available
      URI:  the element namespace name if available
      **/
  static void endElementNs (void *ctx,
                const xmlChar * localname,
                const xmlChar * prefix, const xmlChar * URI)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    printf ("endElementNs: name = '%s' prefix = '%s' uri = '%s'\n", localname,
        prefix, URI);
  }
   /** Display and format an error messages, callback.
      ctx:  an XML parser context
      msg:  the message to display/transmit
      ...:  extra parameters for the message display
      */
  static void error (void *ctx, const char *msg, ...)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    va_list args;
    va_start (args, msg);
    vprintf (msg, args);
    va_end (args);
  }

   /** Display and format a warning messages, callback.
      ctx:  an XML parser context
      msg:  the message to display/transmit
      ...:  extra parameters for the message display
      */
  static void warning (void *ctx, const char *msg, ...)
  {
    ParseFSM & fsm = *(static_cast < ParseFSM * >(ctx));
    va_list args;
    va_start (args, msg);
    vprintf (msg, args);
    va_end (args);
  }
};
int
main (int argc, const char *argv[])
{
  std::string xmlIn = "<a><b><c> text values </c> </b> </a>"
  /*
   * this initialize the library and check potential ABI mismatches
   * between the version it was compiled for and the actual shared
   * library used.
   */
  LIBXML_TEST_VERSION xmlSAXHandler saxHandler; // See http://xmlsoft.org/html/libxml-tree.html#xmlSAXHandler
  memset (&saxHandler, 0, sizeof (saxHandler));
  // Using xmlSAXVersion( &saxHandler, 2 ) generate crash as it sets plenty of other pointers...
  saxHandler.initialized = XML_SAX2_MAGIC;  // so we do this to force parsing as SAX2.
  saxHandler.startElementNs = &ParseFSM::startElementNs;
  saxHandler.endElementNs = &ParseFSM::endElementNs;
  saxHandler.warning = &ParseFSM::warning;
  saxHandler.error = &ParseFSM::error;

  ParseFSM fsm;
  int result =
    xmlSAXUserParseMemory (&saxHandler, &fsm, xmlIn.c_str (),
               int (xmlIn.length ()));
  if (result != 0)
    {
      printf ("Failed to parse document.\n");
      return 1;
    }

  /*
   * Cleanup function for the XML library.
   */
  xmlCleanupParser ();
  /*
   * this is to debug memory for regression tests
   */
  xmlMemoryDump ();

  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
类解析FSM
{
公众:
/**当解析器检测到元素开始时,SAX2回调。它提供元素的名称空间信息,以及元素上的新名称空间声明。
ctx:用户数据(XML解析器上下文)
localname:元素的本地名称
前缀:元素名称空间前缀(如果可用)
URI:元素名称空间名称(如果可用)
nb_名称空间:该节点上的名称空间定义数
名称空间:指向前缀/URI对名称空间定义数组的指针
nb_attributes:该节点上的属性数
nb_defaulted:默认属性的数量。默认属性位于数组的末尾
属性:指向(localname/prefix/URI/value/end)属性值数组的指针。
**/
静态无效StartElements(无效*ctx,
常量xmlChar*localname,
常量xmlChar*前缀,
常量xmlChar*URI,
int nb_名称空间,
常量xmlChar**名称空间,
int nb_属性,
int nb_默认值,常量xmlChar**属性)
{
ParseFSM&fsm=*(静态_cast(ctx));
printf(“StartElements:name='%s'前缀='%s'uri=(%p)'%s'\n',localname,prefix,uri,uri);
for(int indexNamespace=0;indexNamespace=(nb_属性-nb_默认)?“defaulted”:“”,localname,prefix,nsURI,nsURI,value.c_str());
}
}
/**解析器检测到元素结束时的SAX2回调。它提供元素的命名空间信息。
ctx:用户数据(XML解析器上下文)
localname:元素的本地名称
前缀:元素名称空间前缀(如果可用)
URI:元素名称空间名称(如果可用)
**/
静态无效元素(无效*ctx,
常量xmlChar*localname,
常量xmlChar*前缀,常量xmlChar*URI)
{
ParseFSM&fsm=*(静态_cast(ctx));
printf(“endelements:name='%s'前缀='%s'uri='%s'\n”,localname,
前缀(URI);
}
/**显示并格式化错误消息、回调。
ctx:XML解析器上下文
消息:要显示/传输的消息
…:消息显示的额外参数
*/
静态无效错误(无效*ctx,常量字符*msg,…)
{
ParseFSM&fsm=*(静态_cast(ctx));
va_列表参数;
va_启动(args,msg);
vprintf(msg,args);
va_端(args);
}
/**显示并格式化警告消息、回调。
ctx:XML解析器上下文
消息:要显示/传输的消息
…:消息显示的额外参数
*/
静态无效警告(无效*ctx,常量字符*msg,…)
{
ParseFSM&fsm=*(静态_cast(ctx));
va_列表参数;
va_启动(args,msg);
vprintf(msg,args);
va_端(args);
}
};
int
main(int argc,const char*argv[])
{
std::string xmlIn=“文本值”
/*
*这将初始化库并检查潜在的ABI不匹配
*在编译版本和实际共享版本之间
*图书馆使用。
*/
LIBXML_TEST_VERSION xmlSAXHandler saxHandler;//请参阅http://xmlsoft.org/html/libxml-tree.html#xmlSAXHandler
memset(&saxHandler,0,sizeof(saxHandler));
//使用xmlSAXVersion(&saxHandler,2)生成崩溃,因为它设置了大量其他指针。。。
saxHandler.initialized=XML\u SAX2\u MAGIC;//所以我们这样做是为了强制解析为SAX2。
saxHandler.startelements=&ParseFSM::startelements;
saxHandler.endElementNs=&ParseFSM::endElementNs;
saxHandler.warning=&ParseFSM::warning;
saxHandler.error=&ParseFSM::error;
ParseFSM-fsm;
整数结果=
xmlSAXUserParseMemory(&saxHandler,&fsm,xmlIn.c_str(),
int(xmlIn.length());
如果(结果!=0)
{
printf(“解析文档失败。\n”);
返回1;
}
/*
*XML库的清理函数。
*/
xmlcleanuparser();
/*
*这是为了调试回归测试的内存
*/
xmlmoremydump();
返回0;
}
  • 您需要使用回调字符

    无效字符(无效*用户数据, 常量xmlChar*ch, int len)

  • 字符串不是以null结尾的,您需要使用ch,len来确定字符串

  • 这种回调的另一个问题是,它可以在开始和结束元素之间被多次调用。所以你不能盲目地假设你在回拨中得到的是介于t和t之间的字符串