* xmlGetNodePath: * @node: a node * * Build a structure based Path for the given node * * Returns the new path or NULL in case of error. The caller must free * the returned string */
| 4808 | * the returned string |
| 4809 | */ |
| 4810 | xmlChar * |
| 4811 | xmlGetNodePath(const xmlNode *node) |
| 4812 | { |
| 4813 | const xmlNode *cur, *tmp, *next; |
| 4814 | xmlChar *buffer = NULL, *temp; |
| 4815 | size_t buf_len; |
| 4816 | xmlChar *buf; |
| 4817 | const char *sep; |
| 4818 | const char *name; |
| 4819 | char nametemp[100]; |
| 4820 | int occur = 0, generic; |
| 4821 | |
| 4822 | if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) |
| 4823 | return (NULL); |
| 4824 | |
| 4825 | buf_len = 500; |
| 4826 | buffer = (xmlChar *) xmlMallocAtomic(buf_len); |
| 4827 | if (buffer == NULL) |
| 4828 | return (NULL); |
| 4829 | buf = (xmlChar *) xmlMallocAtomic(buf_len); |
| 4830 | if (buf == NULL) { |
| 4831 | xmlFree(buffer); |
| 4832 | return (NULL); |
| 4833 | } |
| 4834 | |
| 4835 | buffer[0] = 0; |
| 4836 | cur = node; |
| 4837 | do { |
| 4838 | name = ""; |
| 4839 | sep = "?"; |
| 4840 | occur = 0; |
| 4841 | if ((cur->type == XML_DOCUMENT_NODE) || |
| 4842 | (cur->type == XML_HTML_DOCUMENT_NODE)) { |
| 4843 | if (buffer[0] == '/') |
| 4844 | break; |
| 4845 | sep = "/"; |
| 4846 | next = NULL; |
| 4847 | } else if (cur->type == XML_ELEMENT_NODE) { |
| 4848 | generic = 0; |
| 4849 | sep = "/"; |
| 4850 | name = (const char *) cur->name; |
| 4851 | if (cur->ns) { |
| 4852 | if (cur->ns->prefix != NULL) { |
| 4853 | snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s", |
| 4854 | (char *)cur->ns->prefix, (char *)cur->name); |
| 4855 | nametemp[sizeof(nametemp) - 1] = 0; |
| 4856 | name = nametemp; |
| 4857 | } else { |
| 4858 | /* |
| 4859 | * We cannot express named elements in the default |
| 4860 | * namespace, so use "*". |
| 4861 | */ |
| 4862 | generic = 1; |
| 4863 | name = "*"; |
| 4864 | } |
| 4865 | } |
| 4866 | next = cur->parent; |
| 4867 |