属性の削除

xmlHasPropで属性を持っているか確認しあと、xmlRemovePropでその属性を削除。

#include <stdio.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>

int del_attribute(xmlNodeSetPtr nodes)
{
    xmlAttrPtr  attr;
    int size;
    int i;

    size = (nodes) ? nodes->nodeNr : 0;
    for(i = 0; i < nodes->nodeNr; ++i) {
        attr = xmlHasProp(nodes->nodeTab[i], "country");
        if (NULL != attr) {
            xmlRemoveProp(attr);
        }
    }

    return size;
}

int execute_xpath(xmlDocPtr doc,
                  xmlChar *xpath_expr, int (*function)(xmlNodeSetPtr))
{
    xmlXPathContextPtr xpath_context;
    xmlXPathObjectPtr  xpath_obj;
    int                ret;

    /* Create xpath evaluation context */
    xpath_context = xmlXPathNewContext(doc);
    if(xpath_context == NULL) {
        fprintf(stderr,"Error: unable to create new XPath context\n");
        xmlFreeDoc(doc);
        return -1;
    }

    /* Evaluate xpath expression */
    xpath_obj = xmlXPathEvalExpression(xpath_expr, xpath_context);
    if(xpath_obj == NULL) {
        fprintf(stderr,
                "Error: unable to evaluate xpath expression \"%s\"\n",
                xpath_expr);
        xmlXPathFreeContext(xpath_context);
        xmlFreeDoc(doc);
        return -1;
    }

    /* Apply function */
    ret = (*function)(xpath_obj->nodesetval);

    /* Cleanup */
    xmlXPathFreeObject(xpath_obj);
    xmlXPathFreeContext(xpath_context);

    return ret;
}

int main(int argc, char **argv)
{
    xmlDocPtr  doc;
    xmlNodePtr root_element = NULL;
    char      *input_file;
    char      *output_file;
    int        ret;

    if (argc != 3) {
        return 1;
    }

    input_file = argv[1];
    output_file = argv[2];

    LIBXML_TEST_VERSION;

    /* Read document */
    doc = xmlReadFile(input_file, NULL, 0);
    if (doc == NULL) {
        fprintf(stderr, "Failed to parse %s\n", input_file);
        return;
    }

    /*Get the root element node */
    root_element = xmlDocGetRootElement(doc);

    /* Del attribute */
    execute_xpath(doc, "/cars/car", del_attribute);

    /* Write document */
    ret = xmlSaveFormatFileEnc(output_file, doc, "UTF-8", 1);
    if (ret < 0) {
        fprintf(stderr, "Failed to save %s\n", output_file);
        return 1;
    }

    /* Free document */
    xmlFreeDoc(doc);

    xmlCleanupParser();

    return 0;
}

入力ファイル

<?xml version="1.0" encoding="UTF-8" ?>
<cars>
  <car country="JP">
    <name>motorcycle</name>
    <price>150</price>
    <img file="car1.jpg"/>
  </car>
  <car country="US">
    <name>truck</name>
    <price>500</price>
    <img file="car2.jpg"/>
  </car>
  <car country="DE">
    <name>car</name>
    <price>200</price>
    <img file="car3.jpg"/>
  </car>
</cars>

出力ファイル

<?xml version="1.0" encoding="UTF-8"?>
<cars>
  <car>
    <name>motorcycle</name>
    <price>150</price>
    <img file="car1.jpg"/>
  </car>
  <car>
    <name>truck</name>
    <price>500</price>
    <img file="car2.jpg"/>
  </car>
  <car>
    <name>car</name>
    <price>200</price>
    <img file="car3.jpg"/>
  </car>
</cars>

tree walk 版

#include <stdio.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/parser.h>

void del_attribute(xmlNodePtr node)
{
    xmlNodePtr  cur_node = NULL;
    xmlAttrPtr  attr;

    for (cur_node = node; cur_node; cur_node = cur_node->next) {
        if ((cur_node->type == XML_ELEMENT_NODE) &&
            (strcmp(cur_node->name, "car") == 0)) {
            attr = xmlHasProp(cur_node, "country");
            if (NULL != attr) {
                xmlRemoveProp(attr);
            }
        }
        else {
            del_attribute(cur_node->children);
        }
    }
}

int main(int argc, char **argv)
{
    xmlDocPtr  doc;
    xmlNodePtr root_element = NULL;
    char      *input_file;
    char      *output_file;
    int        ret;

    if (argc != 3) {
        return 1;
    }

    input_file = argv[1];
    output_file = argv[2];

    LIBXML_TEST_VERSION;

    /* Read document */
    doc = xmlReadFile(input_file, NULL, 0);
    if (doc == NULL) {
        fprintf(stderr, "Failed to parse %s\n", input_file);
        return;
    }

    /*Get the root element node */
    root_element = xmlDocGetRootElement(doc);

    /* Del attribute */
    del_attribute(root_element);

    /* Write document */
    ret = xmlSaveFormatFileEnc(output_file, doc, "UTF-8", 1);
    if (ret < 0) {
        fprintf(stderr, "Failed to save %s\n", output_file);
        return 1;
    }

    /* Free document */
    xmlFreeDoc(doc);

    xmlCleanupParser();

    return 0;
}

参考

The XML C parser and toolkit of Gnome
やさしいXML 第3版

やさしいXML 第3版

やさしいXML 第3版