使用 emacs elisp 解析 XML 并查找嵌套属性
Parsing XML with emacs elisp and finding a nested attribute
我有一些 xml 看起来像这样:
<grammar>
<l>
<f form="paradāra"><s stem=""/><m meaning="anothers wife; adultery"/></f>
<f form="abhimarśeṣu"><s stem="" meaning=""/><m meaning=""/></f>
<f form="pravṛttān"><s stem="" meaning=""/><m meaning=""/></f>
<f form="mahipatis"><s stem="" meaning=""/><m meaning=""/></f>
</l>
<l>
<f form="udvejana"><s stem="udvejana" meaning="agitation, fear"/><m meaning=""/></f>
<f form="karais"><na><ins/><pl/><mas/></na><s stem="kara#1" meaning="action"/><m meaning="by action"/></f>
<f form="daṇḍais"><na><ins/><pl/><mas/></na><na><ins/><pl/><neu/></na><s stem="daṇḍa" meaning="punishment"/><m meaning="by punishment"/></f>
<f form="cihnayitvā"><s stem="" meaning="having marked"/><m meaning=""/></f>
<f form="pravāsayet"><v><cj><ca/></cj><sys><prs><md><op/></md><para/></prs></sys><np><sg/><trd/></np></v><s stem="pravas"/><m meaning="to put on, dress"/></f>
</l>
</grammar>
现在我通过 运行 (xml-parse-region) 将其转换为 S 表达式。它 returns 是这样的:
((grammar nil "
" (l nil "
" (f ((form . "paradāra")) (s ((stem . ""))) (m ((meaning . "anothers wife; adultery")))) "
" (f ((form . "abhimarśeṣu")) (s ((stem . "") (meaning . ""))) (m ((meaning . "")))) "
" (f ((form . "pravṛttān")) (s ((stem . "") (meaning . ""))) (m ((meaning . "")))) "
" (f ((form . "mahipatis")) (s ((stem . "") (meaning . ""))) (m ((meaning . "")))) "
") "
" (l nil "
" (f ((form . "udvejana")) (s ((stem . "udvejana") (meaning . "agitation, fear"))) (m ((meaning . "")))) "
" (f ((form . "karais")) (na nil (ins nil) (pl nil) (mas nil)) (s ((stem . "kara#1") (meaning . "action"))) (m ((meaning . "by action")))) "
" (f ((form . "daṇḍais")) (na nil (ins nil) (pl nil) (mas nil)) (na nil (ins nil) (pl nil) (neu nil)) (s ((stem . "daṇḍa") (meaning . "punishment"))) (m ((meaning . "by punishment")))) "
" (f ((form . "cihnayitvā")) (s ((stem . "") (meaning . "having marked"))) (m ((meaning . "")))) "
" (f ((form . "pravāsayet")) (v nil (cj nil (ca nil)) (sys nil (prs nil (md nil (op nil)) (para nil))) (np nil (sg nil) (trd nil))) (s ((stem . "pravas"))) (m ((meaning . "to put on, dress")))) "
") "
"))
我现在要做的是提取所有以 (s ... ) 开头的子节点,并将它们收集到一个单独的缓冲区中。喜欢:
(s ((stem . "udvejana") (meaning . "agitation, fear")))
代码会是什么样子?递归遍历树?昨天我走到了第一个 (l ... ) 节点,但由于停电,我丢失了代码。希望大家给点建议!
你只需要基本的递归:
(defun rec-filter (predicate seq &optional acc)
(cond ((null seq)
acc)
((consp seq)
(append (rec-filter predicate (car seq) nil)
(rec-filter predicate (cdr seq) nil)
(if (funcall predicate seq)
(cons seq acc)
acc)))
(t
acc)))
(rec-filter
(lambda (x) (eq (car x) 's))
tree)
;; =>
;; ((s ((stem . "")))
;; (s ((stem . "")
;; (meaning . "")))
;; (s ((stem . "")
;; (meaning . "")))
;; (s ((stem . "")
;; (meaning . "")))
;; (s ((stem . "udvejana")
;; (meaning . "agitation, fear")))
;; (s ((stem . "kara#1")
;; (meaning . "action")))
;; (s ((stem . "daṇḍa")
;; (meaning . "punishment")))
;; (s ((stem . "")
;; (meaning . "having marked")))
;; (s ((stem . "pravas"))))
我有一些 xml 看起来像这样:
<grammar>
<l>
<f form="paradāra"><s stem=""/><m meaning="anothers wife; adultery"/></f>
<f form="abhimarśeṣu"><s stem="" meaning=""/><m meaning=""/></f>
<f form="pravṛttān"><s stem="" meaning=""/><m meaning=""/></f>
<f form="mahipatis"><s stem="" meaning=""/><m meaning=""/></f>
</l>
<l>
<f form="udvejana"><s stem="udvejana" meaning="agitation, fear"/><m meaning=""/></f>
<f form="karais"><na><ins/><pl/><mas/></na><s stem="kara#1" meaning="action"/><m meaning="by action"/></f>
<f form="daṇḍais"><na><ins/><pl/><mas/></na><na><ins/><pl/><neu/></na><s stem="daṇḍa" meaning="punishment"/><m meaning="by punishment"/></f>
<f form="cihnayitvā"><s stem="" meaning="having marked"/><m meaning=""/></f>
<f form="pravāsayet"><v><cj><ca/></cj><sys><prs><md><op/></md><para/></prs></sys><np><sg/><trd/></np></v><s stem="pravas"/><m meaning="to put on, dress"/></f>
</l>
</grammar>
现在我通过 运行 (xml-parse-region) 将其转换为 S 表达式。它 returns 是这样的:
((grammar nil "
" (l nil "
" (f ((form . "paradāra")) (s ((stem . ""))) (m ((meaning . "anothers wife; adultery")))) "
" (f ((form . "abhimarśeṣu")) (s ((stem . "") (meaning . ""))) (m ((meaning . "")))) "
" (f ((form . "pravṛttān")) (s ((stem . "") (meaning . ""))) (m ((meaning . "")))) "
" (f ((form . "mahipatis")) (s ((stem . "") (meaning . ""))) (m ((meaning . "")))) "
") "
" (l nil "
" (f ((form . "udvejana")) (s ((stem . "udvejana") (meaning . "agitation, fear"))) (m ((meaning . "")))) "
" (f ((form . "karais")) (na nil (ins nil) (pl nil) (mas nil)) (s ((stem . "kara#1") (meaning . "action"))) (m ((meaning . "by action")))) "
" (f ((form . "daṇḍais")) (na nil (ins nil) (pl nil) (mas nil)) (na nil (ins nil) (pl nil) (neu nil)) (s ((stem . "daṇḍa") (meaning . "punishment"))) (m ((meaning . "by punishment")))) "
" (f ((form . "cihnayitvā")) (s ((stem . "") (meaning . "having marked"))) (m ((meaning . "")))) "
" (f ((form . "pravāsayet")) (v nil (cj nil (ca nil)) (sys nil (prs nil (md nil (op nil)) (para nil))) (np nil (sg nil) (trd nil))) (s ((stem . "pravas"))) (m ((meaning . "to put on, dress")))) "
") "
"))
我现在要做的是提取所有以 (s ... ) 开头的子节点,并将它们收集到一个单独的缓冲区中。喜欢:
(s ((stem . "udvejana") (meaning . "agitation, fear")))
代码会是什么样子?递归遍历树?昨天我走到了第一个 (l ... ) 节点,但由于停电,我丢失了代码。希望大家给点建议!
你只需要基本的递归:
(defun rec-filter (predicate seq &optional acc)
(cond ((null seq)
acc)
((consp seq)
(append (rec-filter predicate (car seq) nil)
(rec-filter predicate (cdr seq) nil)
(if (funcall predicate seq)
(cons seq acc)
acc)))
(t
acc)))
(rec-filter
(lambda (x) (eq (car x) 's))
tree)
;; =>
;; ((s ((stem . "")))
;; (s ((stem . "")
;; (meaning . "")))
;; (s ((stem . "")
;; (meaning . "")))
;; (s ((stem . "")
;; (meaning . "")))
;; (s ((stem . "udvejana")
;; (meaning . "agitation, fear")))
;; (s ((stem . "kara#1")
;; (meaning . "action")))
;; (s ((stem . "daṇḍa")
;; (meaning . "punishment")))
;; (s ((stem . "")
;; (meaning . "having marked")))
;; (s ((stem . "pravas"))))