Click here to Skip to main content
15,912,977 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
The xml example, the lang attribute contains single quote and double quotation marks at same time
XML
<?xml version="1.0" encoding="UTF-8"?>
<test>
	<node lang="'"word" />
</test>


What I have tried:

I write a C program, but it prompt me that
XPath error : Invalid predicate
//node[@lang=''"word']


C++
/*
gcc -g `xml2-config --cflags` test.c `xml2-config --libs`
*/

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>

#define XML_FILE_PATH "test.xml"

int main(void)
{
	xmlDocPtr doc = NULL;
	xmlXPathObjectPtr object = NULL;
	xmlXPathContextPtr context = NULL;
	xmlNodePtr curr = NULL;
	xmlNodeSetPtr pNodeSet = NULL;
	xmlChar* prop = NULL;
	char lang[] = "'\"word";
	char xpath[256];

	doc = xmlParseFile(XML_FILE_PATH);
	if (NULL == doc) {
		printf("xmlParseFile failed");
		return -1;
	}
	context = xmlXPathNewContext(doc);
	if (NULL == context) {
		printf("xmlXPathNewContext failed");
		return -1;
	}
	
	/* Create Object */
	snprintf(xpath, sizeof(xpath), "//node[@lang='%s']", lang);
	object = xmlXPathEvalExpression((xmlChar*)xpath, context);
	xmlXPathFreeContext(context);
	if (object == NULL) {
		printf("xmlXPathEvalExpression (%s) failed", xpath);
		return -1;
	}
	
	/* NodeSet Is Empty ? */
	if(xmlXPathNodeSetIsEmpty(object->nodesetval)) {
		xmlXPathFreeObject(object);
		printf("xmlXPathNodeSetIsEmpty");
		return 0;
	}

	pNodeSet = object->nodesetval;
	curr = pNodeSet->nodeTab[0];

	prop = xmlGetProp(curr, (xmlChar *)"lang");
	printf("xmlGetProp %s", prop);
	xmlFree(prop);
	xmlXPathFreeObject(object);
	xmlFreeDoc(doc);

	return 0;
}
Posted
Updated 8-Feb-18 22:03pm
Comments
Maciej Los 9-Feb-18 2:35am    
Seems that xml is not well formed...

1 solution

You have to use character references or entities (List of XML and HTML character entity references - Wikipedia[^]).

In your case it would be:
char lang[] = "&apos;&quot;word";

You can also write a function to do that:
// Or use boost::replace_all
void replace_all(std::string& str, const std::string& search, const std::string& replace)
{
    size_t len = search.length();
    size_t pos = str.find(search);
    while (std::string::npos != npos)
    {
        str.replace(pos, len, replace);
        pos = str.find(search, pos + len);
    }
}

void Xmlify(std::string& str)
{
    replace_all(str, "&", "&amp;"); // Must be the first
    replace_all(str, "<", "&lt;");
    replace_all(str, ">", "&gt;");
    replace_all(str, "\"", "&quot;");
    replace_all(str, "'", "&apos;");
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900