我正在开发一些从xml doc中检索某些值的过程,并使用嵌套的struct指针来帮助我管理数据。
我遇到了来自我的一个结构中的字符串值的意外行为:
这是程序:
void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
do {
if (xmlStrcmp (node->name, XMLSTR("AdSystem")) == 0){
xmlFile->Ads->data->Inline->AdSystem = (char *)node->children->content; // does not work - displays �9;
xmlFile->Ads->data->Inline->AdSystem = "Works"; // works
printf ((char *)node->children->content); // works
}
else if (xmlStrcmp (node->name, XMLSTR("Creatives")) == 0){
parseCreatives (doc, node->children, xmlFile);
}
} while((node = node->next));
}
这是我遇到的问题:
xmlFile->Ads->data->Inline->AdSystem = (char *)node->children->content;
当我在我的程序中测试结果时,该值看起来并没有指向内存中的正确位置,因为它产生垃圾,即:"�9"其中预期值是"广告系统"
如果我存储测试值" Works" - 这里没问题
如果我打印节点值,这也有效:"广告系统"
提前致谢
- HEADER FILE
/*
* daastXML.h
*
* Created on: Nov 27, 2015
* Author: hearme
*/
#ifndef DAASTXML_H_
#define DAASTXML_H_
#define VECTOR_INITIAL_CAPACITY 100
// Define a vector type
typedef struct {
int size; // slots used so far
int capacity; // total available slots
struct daastAd *data; // array of ads we're storing
char * testData;
} VectorAds;
typedef struct {
int size; // slots used so far
int capacity; // total available slots
struct daastCreative *data; // array of ads we're storing
} VectorCreatives;
typedef struct {
int size;
int capacity;
struct daastMediaFile *data;
} VectorMediaFiles;
struct daastInline {
// Required elements
char *AdTitle;
char *Impression;
VectorCreatives *Creatives;
char *Category;
// Optional elements
char *AdSystem;
char *Description;
char *Advertiser;
char *Expires;
// Multiple survey urls
// Multiple error urls
char *Pricing;
// Extensions - for custom xml extensions
};
struct daastXML {
char *version;
VectorAds *Ads;
};
struct daastAd {
char *id;
char *sequence;
struct daastInline *Inline;
};
struct daastMediaFile {
char *id;
char *delivery;
char *type;
char *url;
char *bitRate;
};
struct daastLinear {
char *duration;
VectorMediaFiles MediaFiles;
};
struct daastCreative {
struct daastLinear linear;
};
// Main handler
void processDaast (char * filePath, struct daastXML *xmlFile);
// Methods used to manage Ads collection
void vectorAds_init(VectorAds *vector);
void vectorAds_append(VectorAds *vector, struct daastAd value);
struct daastAd vectorAds_get(VectorAds *vector, int index);
void vectorAds_set(VectorAds *vector, int index, struct daastAd value);
void vectorAds_double_capacity_if_full(VectorAds *vector);
void vectorAds_free(VectorAds *vector);
// Methods used to manage Creatives collection
void vectorCreatives_init(VectorCreatives *vector);
void vectorCreatives_append(VectorCreatives *vector, struct daastCreative value);
struct daastCreative VectorCreatives_get(VectorCreatives *vector, int index);
void vectorCreatives_set(VectorCreatives *vector, int index, struct daastCreative value);
void vectorCreatives_double_capacity_if_full(VectorCreatives *vector);
void vectorCreatives_free(VectorCreatives *vector);
// Methods used to manage Creatives collection
void vectorMediaFiles_init(VectorMediaFiles *vector);
void vectorMediaFiles_append(VectorMediaFiles *vector, struct daastMediaFile value);
struct daastMediaFile vectorMediaFiles_get(VectorMediaFiles *vector, int index);
void vectorMediaFiles_set(VectorMediaFiles *vector, int index, struct daastMediaFile value);
void vectorMediaFiles_double_capacity_if_full(VectorMediaFiles *vector);
void vectorMediaFiles_free(VectorMediaFiles *vector);
#endif /* DAASTXML_H_ */
C档案 / * * daastXML.c * *创建日期:2015年11月27日 *作者:听到 * /
#ifndef DAASTXML_C_
#define DAASTXML_C_
#define XMLSTR(str) ((xmlChar *)(str))
#include "daastXML.h"
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void parseAds(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseInline(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseCreatives(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseCreativesElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseCreativeElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseLinear (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseMediaFiles (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void processDaast (char * filePath, struct daastXML *xmlFile){
xmlDocPtr doc;
xmlNodePtr node;
doc = xmlParseFile(filePath);
node = xmlDocGetRootElement(doc);
if (xmlStrcmp (node->name, XMLSTR("DAAST")) == 0){
xmlFile->version = (char *)xmlGetProp(node, XMLSTR("version"));
parseAds(doc, node->children, xmlFile);
}
xmlFreeDoc(doc);
}
void parseAds(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
// Allocate new instance of the VectorAds and assign it to the xmlFile, set default data
VectorAds *Ads;
Ads = (VectorAds *) malloc (sizeof(VectorAds));
Ads->testData = "testData";
xmlFile->Ads = Ads;
// Initialise the vector
vectorAds_init(xmlFile->Ads);
do {
if (node == NULL) break;
if (xmlIsBlankNode(node)) continue;
if (xmlStrcmp (node->name, XMLSTR("Ad")) == 0) {
// Set up new advert
struct daastAd *newAd;
newAd = (struct daastAd *) malloc (sizeof(struct daastAd));
// Set add properties
newAd->id = (char *)xmlGetProp(node, XMLSTR("id"));
newAd->sequence = (char *)xmlGetProp(node, XMLSTR("sequence"));
vectorAds_append(xmlFile->Ads, *newAd);
// At this point we need to get the inline (or wrapper) info *** WRAPPER NOT INTEGRATED ***
parseInline (doc, node->children, xmlFile);
}
} while ((node = node->next));
}
void parseInline (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
// Set up Inline Property Here
struct daastInline *Inline;
Inline = (struct daastInline *) malloc (sizeof(struct daastInline));
// Assing Inline Property
xmlFile->Ads->data->Inline = Inline;
do {
if (node->type == XML_ELEMENT_NODE){
if (xmlStrcmp (node->name, XMLSTR("InLine")) == 0){
// Various parses at this level
parseInlineElements(doc, node->children, xmlFile);
//xmlFile->Ads->data->Inline->AdSystem = "AdSystem";
// Should this be here?
//parseCreatives (doc, node->children, xmlFile);
break;
}
}
} while((node = node->next));
}
void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
// loop through Inline child elements, and pick out the values
//*
do {
if (xmlStrcmp (node->name, XMLSTR("AdSystem")) == 0){
char *nodeValue = (char *) node->children->content;
xmlFile->Ads->data->Inline->AdSystem = malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue);
}
else if (xmlStrcmp (node->name, XMLSTR("AdTitle")) == 0){
char *nodeValue = (char *) node->children->content;
xmlFile->Ads->data->Inline->AdTitle = malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->AdTitle, nodeValue);
}
else if (xmlStrcmp (node->name, XMLSTR("Category")) == 0){
char *nodeValue = "";
nodeValue = (char *) node->children->content;
xmlFile->Ads->data->Inline->Category = malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->Category, nodeValue);
}
else if (xmlStrcmp (node->name, XMLSTR("Advertiser")) == 0){
char *nodeValue = (char *) node->children->content;
xmlFile->Ads->data->Inline->Advertiser = malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->Advertiser, nodeValue);
}
else if (xmlStrcmp (node->name, XMLSTR("Pricing")) == 0){
char *nodeValue = (char *) node->children->content;
xmlFile->Ads->data->Inline->Pricing = malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->Pricing, nodeValue);
}
else if (xmlStrcmp (node->name, XMLSTR("Expires")) == 0){
char *nodeValue = (char *) node->children->content;
xmlFile->Ads->data->Inline->Expires = malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->Expires, nodeValue);
}
// else if (xmlStrcmp (node->name, XMLSTR("Impression")) == 0){
// char *nodeValue = (char *) node->children->next->content;
// xmlFile->Ads->data->Inline->Impression = malloc (sizeof(char));
// strcpy (xmlFile->Ads->data->Inline->Impression, nodeValue);
//
// }
else if (xmlStrcmp (node->name, XMLSTR("Creatives")) == 0){
parseCreatives (doc, node->children, xmlFile);
}
} while((node = node->next));
}
void parseCreatives(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
// Need to set up a new Creatives and assign it to the nested struct pointer
VectorCreatives *Creatives;
Creatives = (VectorCreatives *) malloc (sizeof(VectorCreatives));
VectorAds *Ads;
Ads = (VectorAds *) malloc (sizeof(VectorAds));
xmlFile->Ads->data->Inline->Creatives = Creatives;
vectorCreatives_init(xmlFile->Ads->data->Inline->Creatives);
//*parseCreativesElements(doc, node->next, xmlFile);
}
void parseCreativesElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
do {
// Loop through the creatives - find the individual Creatives
if (xmlStrcmp (node->name, XMLSTR("Creative")) == 0){
// Various parses at this level
parseCreativeElements(doc, node->children, xmlFile);
}
} while ((node = node->next));
}
void parseCreativeElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
do {
if (xmlStrcmp (node->name, XMLSTR("Linear")) == 0){
// Linear branch
parseLinear(doc, node->children, xmlFile);
} else if (xmlStrcmp (node->name, XMLSTR("CompanionAds")) == 0){
// Companion Ad branch
}
} while ((node = node->next));
}
void parseLinear(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
do {
if (xmlStrcmp (node->name, XMLSTR("Duration")) == 0){
struct daastCreative newCreative;
//*newCreative.linear.duration = node->children->content;
//*vectorCreatives_append(&xmlFile->Ads.data->Inline.Creatives, newCreative);
} else if (xmlStrcmp (node->name, XMLSTR("MediaFiles")) == 0){
//parseMediaFiles(doc,node->children,xmlFile);
}
} while ((node = node->next));
}
void parseMediaFiles(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){
//* vectorMediaFiles_init(&xmlFile->Ads.data->Inline.Creatives.data->linear.MediaFiles);
do {
// Store all occurrences of Media Files
if (xmlStrcmp (node->name, XMLSTR("MediaFile")) == 0){
// Create a new Media File, and append
struct daastMediaFile newMediaFile;
newMediaFile.url = (char *) node->children->next->content;
newMediaFile.id = (char *)xmlGetProp(node, XMLSTR("id"));
newMediaFile.type = (char *)xmlGetProp(node, XMLSTR("type"));
newMediaFile.bitRate = (char *)xmlGetProp(node, XMLSTR("bitrate"));
newMediaFile.delivery = (char *)xmlGetProp(node, XMLSTR("delivery"));
//*vectorMediaFiles_append(&xmlFile->Ads.data->Inline.Creatives.data->linear.MediaFiles, newMediaFile);
}
} while ((node = node->next));
}
// ***************************************************************
// ***************************************************************
// ***************************************************************
// ***************************************************************
// Methods to manage collection (Ads)
void vectorAds_init(VectorAds *vector) {
// initialize size and capacity
vector->size = 0;
vector->capacity = VECTOR_INITIAL_CAPACITY;
// allocate memory for vector->data
vector->data = malloc(sizeof(struct daastAd) * vector->capacity);
}
void vectorAds_append(VectorAds *vector, struct daastAd value) {
// make sure there's room to expand into
vectorAds_double_capacity_if_full(vector);
// append the value and increment vector->size
vector->data[vector->size++] = value;
}
struct daastAd vectorAds_get(VectorAds *vector, int index) {
if (index >= vector->size || index < 0) {
printf("Index %d out of bounds for vector of size %d\n", index, vector->size);
exit(1);
}
return vector->data[index];
}
void vectorAds_set(VectorAds *vector, int index, struct daastAd value) {
// zero fill the vector up to the desired index
struct daastAd zero;
while (index >= vector->size) {
vectorAds_append(vector, zero);
}
// set the value at the desired index
vector->data[index] = value;
}
void vectorAds_double_capacity_if_full(VectorAds *vector) {
if (vector->size >= vector->capacity) {
// double vector->capacity and resize the allocated memory accordingly
vector->capacity *= 2;
vector->data = realloc(vector->data, sizeof(struct daastAd) * vector->capacity);
}
}
void vectorAds_free(VectorAds *vector) {
free(vector->data);
}
// Methods to manage Creatives Vector
void vectorCreatives_init(VectorCreatives *vector) {
// initialize size and capacity
vector->size = 0;
vector->capacity = VECTOR_INITIAL_CAPACITY;
// allocate memory for vector->data
vector->data = malloc(sizeof(struct daastCreative) * vector->capacity);
}
void vectorCreatives_append(VectorCreatives *vector, struct daastCreative value) {
// make sure there's room to expand into
vectorCreatives_double_capacity_if_full(vector);
// append the value and increment vector->size
vector->data[vector->size++] = value;
}
struct daastCreative vectorCreatives_get(VectorCreatives *vector, int index) {
if (index >= vector->size || index < 0) {
printf("Index %d out of bounds for vector of size %d\n", index, vector->size);
exit(1);
}
return vector->data[index];
}
void vectorCreatives_set(VectorCreatives *vector, int index, struct daastCreative value) {
// zero fill the vector up to the desired index
struct daastCreative zero;
while (index >= vector->size) {
vectorCreatives_append(vector, zero);
}
// set the value at the desired index
vector->data[index] = value;
}
void vectorCreatives_double_capacity_if_full(VectorCreatives *vector) {
if (vector->size >= vector->capacity) {
// double vector->capacity and resize the allocated memory accordingly
vector->capacity *= 2;
vector->data = realloc(vector->data, sizeof(struct daastCreative) * vector->capacity);
}
}
void vectorCreatives_free(VectorCreatives *vector) {
free(vector->data);
}
// Methods used to manage MediaFiles Vector
void vectorMediaFiles_init(VectorMediaFiles *vector) {
// initialize size and capacity
vector->size = 0;
vector->capacity = VECTOR_INITIAL_CAPACITY;
// allocate memory for vector->data
vector->data = malloc(sizeof(struct daastMediaFile) * vector->capacity);
}
void vectorMediaFiles_append(VectorMediaFiles *vector, struct daastMediaFile value) {
// make sure there's room to expand into
vectorMediaFiles_double_capacity_if_full(vector);
// append the value and increment vector->size
vector->data[vector->size++] = value;
}
struct daastMediaFile vectorMediaFiles_get(VectorMediaFiles *vector, int index) {
if (index >= vector->size || index < 0) {
printf("Index %d out of bounds for vector of size %d\n", index, vector->size);
exit(1);
}
return vector->data[index];
}
void vectorMediaFiles_set(VectorMediaFiles *vector, int index, struct daastMediaFile value) {
// zero fill the vector up to the desired index
struct daastMediaFile zero;
while (index >= vector->size) {
vectorMediaFiles_append(vector, zero);
}
// set the value at the desired index
vector->data[index] = value;
}
void vectorMediaFiles_double_capacity_if_full(VectorMediaFiles *vector) {
if (vector->size >= vector->capacity) {
// double vector->capacity and resize the allocated memory accordingly
vector->capacity *= 2;
vector->data = realloc(vector->data, sizeof(struct daastMediaFile) * vector->capacity);
}
}
void vectorMediaFiles_free(VectorMediaFiles *vector) {
free(vector->data);
}
#endif /* DAASTXML_C_ */
链接到XML:http://hearme.fm/ars.xml
答案 0 :(得分:1)
行,
我已经修复了错误,但它看起来并不是最干净的代码,也许有人可以告诉我这是否合适?
@users
答案 1 :(得分:0)
我已修复错误,但它看起来并不是最干净的代码,也许 有人可以建议这是否合适?
char *nodeValue = (char*) node->children->content; xmlFile->Ads->data->Inline->AdSystem = (char *) malloc (sizeof(char)); strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue);
Sami Kuhmonen和Lundin已经注意到分配的大小不是。
回到原来的问题,有没有人有简单有效的 从节点值中分配值的方式?这似乎更多 比应该是复杂的
你是对的;如果您有POSIX系统,可以使用strdup()
:
xmlFile->Ads->data->Inline->AdSystem = strdup((char *)node->children->content);