我正在尝试使用C和libxml2库更新XML文档。 我想有选择地根据一些配置值更新XML元素和/或属性。
看起来我可以使用xmlSetProp
来更新XML属性,但我看不出如何使用它来更新XML元素值。似乎在使用xmlSetProp
时它会添加一个新属性,但我认为我可以通过先删除属性来解决这个问题。
请有人告诉我如何使用libxml2库来更新元素。为了给出一些上下文,我希望能够处理以下XML并更新值:
<person sex="female">
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
所以好像我可以使用xmlSetProp
更新性别属性,但是如何更新名字的值呢?
提前感谢您的帮助。
在你们的帮助下,我写下了我需要的东西(下面)并希望它能使其他人受益。
由于
xmlXPathObjectPtr GetNodeSet(const xmlDocPtr pDoc, xmlChar* pszXPath)
{
static const char szFctName[]= __FUNCTION__;
xmlXPathContextPtr pContext = NULL;
xmlXPathObjectPtr pResult = NULL;
Debug("%s '%s'\n", szFctName, pszXPath);
pContext = xmlXPathNewContext(pDoc);
if (pContext == NULL)
{
Debug("Error in xmlXPathNewContext pContext is NULL\n");
return NULL;
}
pResult = xmlXPathEvalExpression(pszXPath, pContext);
xmlXPathFreeContext(pContext);
if (pResult == NULL)
{
Debug("Error in xmlXPathEvalExpression pResult is NULL\n");
return NULL;
}
if (xmlXPathNodeSetIsEmpty(pResult->nodesetval))
{
xmlXPathFreeObject(pResult);
Debug("No results found\n");
return NULL;
}
return pResult;
}
xmlDocPtr GetXMLDoc(char* pszXMLFilename)
{
static const char szFctName[]= __FUNCTION__;
xmlDocPtr pDoc = xmlParseFile(pszXMLFilename);
Debug("%s '%s'\n", szFctName, pszXMLFilename);
if (pDoc == NULL )
{
Debug("Document: '%s' not parsed successfully. \n", pszXMLFilename);
return NULL;
}
return pDoc;
}
// Some code below (extracted and modified so won't compile purely for example) that is used to update the XML
// xmllib vars
xmlNodePtr pNode = NULL;
xmlDocPtr pDoc = NULL;
xmlNodeSetPtr pNodeSet = NULL;
xmlXPathObjectPtr pResult = NULL;
// Get the XML doc
pDoc = GetXMLDoc(pszXMLFilename);
// Using XPath to navigate to element.
pResult = GetNodeSet(pDoc, "/configuration/appSettings/add[@key='KeyToSearchFor']");
if (pResult && pResult->nodesetval)
{
pNodeSet = pResult->nodesetval;
for (iNodeSetValue = 0; iNodeSetValue < pNodeSet->nodeNr; iNodeSetValue++)
{
if (pNodeSet->nodeTab)
{
pNode = pNodeSet->nodeTab[iNodeSetValue];
if (pNode)
{
if (ItsAnElement /*I configured this*/)
{
xmlNodeSetContent(pNode, szNewXMLValue);
}
else if (ItsAnAttribute /*I configured this*/)
{
if (xmlGetProp(pNode, XML_ATTRIBUTE_NODE_VALUE_NAME))
{
xmlSetProp(pNode, BAD_CAST XML_ATTRIBUTE_NODE_VALUE_NAME, szNewXMLValue);
}
else
{
Debug("%s Couldn't find XML property value for: '%s'\n", szFctName, pParams[iTag].szXMLTagXPathValue);
}
}
}
}
}
}
// We're about to save our changes. Backup the file first and only update if this succeeds
if (BackupXMLFile(pszXMLFilename))
{
// Returns: The number of bytes written or -1 in case of failure.
if (xmlSaveFileEnc(pszXMLFilename, pDoc, "utf-8") >= 0)
{
iStatus = E_OK;
}
else
{
Debug("%s xmlSaveFileEnc failed\n", szFctName);
}
}
else
{
iStatus = E_ERR;
}
xmlFreeDoc(pDoc);