Reputation: 298
I have an XML file, which contains several nested groups, e.g.
<?xml encoding="utf-8"?>
<MainNode
attribute1='values'
attribute2='values'/>
<SubNode1 attribute1='values'>
<Sub-SubNode1 attribute1='values'> ;; I want this value, only if
<Node-Of-Interest> ;; This exists
<Attribute1 value="value1"/> ;; And this is a specific value
<Attribute2 value="value2"/>
</Node-Of-Interest>
</Sub-SubNode1>
</SubNode1>
<SubNode1 attribute1='values'>
</Sub-SubNode1 attribute1='values'>
</SubNode1>
</MainNode>
The XML file may have several nodes of the type SubNode1, all named the same; I am, however, interested in only that which contains the Node-Of-Interest, specifically if the attribute Attribute1 has a specific value, I want the value of parent attribute in Sub-SubNode1 attribute1.
I have tried using the supplied xml.el functions xml-parse-region
,xml-get-attributes
andxml-get-children
to give me a structure as below:
((SubNode1 ((attribute1 . "values")) "
" (Sub-SubNode1 ((attribute1 . "values")) "
" (Node-Of-Interest nil "
" (Attribute1 ((value . "value1"))) "
" (Attribute2 ((value . "value2"))) "
") "
") "
")
(SubNode1 ((attribute1 . "values")) "
" (Sub-SubNode1 ((attribute1 . "values"))) "
"))
My problem now is, how to walk this list to find the values I would like?
Upvotes: 4
Views: 486
Reputation: 20352
Just a basic tree walk:
(setq tree
'((MainNode ((attribute1 . "values")
(attribute2 . "values"))
" " (SubNode1 ((attribute1 . "values"))
" " (Sub-SubNode1 ((attribute1 . "values"))
" "
(Node-Of-Interest
nil
" "
(Attribute1 ((value . "value1")))
" "
(Attribute2 ((value . "value2")))
" ")
" ")
" ")
" " (SubNode1 ((attribute1 . "values"))
" " (Sub-SubNode1 ((attribute1 . "values")))
" ")
" ")))
(defun my-recurse (lst fun)
(when (consp lst)
(append (and (funcall fun lst) (list lst))
(my-recurse (car lst) fun)
(my-recurse (cdr lst) fun))))
(require 'cl-lib)
(my-recurse
tree
(lambda (x)
(and (listp x) (symbolp (car x)) (listp (cdr x))
(cl-find-if
(lambda (y)
(and (consp y) (eq (car y) 'Node-Of-Interest)))
x))))
;; =>
;; ((Sub-SubNode1
;; ((attribute1 . "values"))
;; " " (Node-Of-Interest
;; nil " "
;; (Attribute1 ((value . "value1")))
;; " "
;; (Attribute2 ((value . "value2")))
;; " ")
;; " "))
Btw, your XML is broken according to the Emacs validator.
Upvotes: 2