2009-07-28 51 views
64

Tôi không thể tìm thấy bất kỳ thông tin nào về cách phân tích cú pháp tài liệu xml và các thành phần truy cập.Phân tích cú pháp của Clojure

Tôi đã tìm thấy hai cách để phân tích các tài liệu xml

(clojure.zip/xml-zip (clojure.xml/parse file)) 

(parse-seq file) 

nhưng tôi có thể dường như tìm thấy bất kỳ thông tin về làm thế nào để xử lý cấu trúc kết quả?

Tệp nguồn đề cập đến truy vấn zip.clj về cách truy vấn kết quả nhưng điều đó dường như cũng bị thiếu.

+2

Các ví dụ từ zip-query.clj có thể được tìm thấy trong xml_test.clj nằm trong src/test/clojure/clojure/data/zip trong repo github cho clojure.data.zip –

+0

Vui, tôi đã hỏi điều này là tốt, và có câu trả lời tuyệt vời từ một số người hữu ích nhất trên SO. Tuy nhiên, ngay cả sau khi chạy dữ liệu được phân tích kết quả.xml thông qua một trong những gợi ý, cấu trúc kết quả vẫn không có nhiều ý nghĩa với tôi. Tôi sẽ xem xét xml-zip của bạn, trừ khi data.xml là người kế thừa của nó. – octopusgrabbus

Trả lời

81

Giả sử bạn có xml sau đây để phân tích trong tập tin của bạn:

<high-node> 
    <low-node>my text</low-node> 
</high-node> 

bạn nạp clojure.xml:

user=> (use 'clojure.xml) 

khi phân tích cú pháp, xml sẽ có cấu trúc sau:

{:tag :high-node, :attrs nil, :content [{:tag :low-node, :attrs nil, :content ["my text"]}]} 

và sau đó bạn có thể seq qua nội dung của tệp để lấy nội dung thứ e low-node:

user=> (for [x (xml-seq 
       (parse (java.io.File. file))) 
       :when (= :low-node (:tag x))] 
     (first (:content x))) 

("my text") 

Tương tự, nếu bạn muốn có quyền truy cập vào toàn bộ danh sách các thông tin trên nút thấp, bạn sẽ thay đổi :when vị để (= (:high-node (:tag x))):

user=> (for [x (xml-seq 
       (parse (java.io.File. file))) 
       :when (= :high-node (:tag x))] 
     (first (:content x))) 

({:tag :low-node, :attrs nil, :content ["my text"]}) 

này hoạt động vì các từ khóa có thể hoạt động như các hàm. Xem Questions about lists and other stuff in ClojureData Structures: Keywords

+0

Câu trả lời xuất sắc! –

+0

Giải thích rất hay! Tôi sẽ thử cái này. – Ralph

+0

(từ chối trách nhiệm: Tôi là một clojure newb) ... Nhưng tôi thấy điều này làm việc cho tôi trong REPL, và tôi không thể làm cho nó làm việc trong một tập tin (sự thiếu hiểu biết của tôi là để đổ lỗi). Các clojure.data.zip.xml làm việc cho tôi trong một tập tin mà không sửa đổi. – wonderfulthunk

52

Câu trả lời ở trên hoạt động nhưng tôi thấy dễ sử dụng hơn clojure.data.zip.xml (trước đây là clojure-contrib.zip-filter.xml trước Clojure 1.3).

file:

myfile.xml:

<songs> 
    <track id="t1"><name>Track one</name></track> 
    <track id="t2"><name>Track two</name></track> 
</songs> 

mã:

; Clojure 1.3 
(ns example 
    (:use [clojure.data.zip.xml :only (attr text xml->)]) ; dep: see below 
    (:require [clojure.xml :as xml] 
      [clojure.zip :as zip])) 

(def xml (xml/parse "myfile.xml")) 
(def zipped (zip/xml-zip xml)) 
(xml-> zipped :track :name text)  ; ("Track one" "Track two") 
(xml-> zipped :track (attr :id))  ; ("t1" "t2") 

Thật không may, bạn cần phải kéo trong một sự phụ thuộc vào data.zip để có được chức năng đọc/lọc đẹp này. Nó có giá trị phụ thuộc :) Trong lein nó sẽ là (tính 17-Aug-2013):

[org.clojure/data.zip "0.1.1"] 

Và như đối với tài liệu cho data.zip.xml ... Tôi chỉ cần nhìn vào các tập tin nguồn tương đối nhỏ here để xem điều gì là có thể. Một câu trả lời SO tốt khác là here.

+2

Điều này làm việc tuyệt vời cho tôi trong một dự án tôi đang làm việc trên. – wonderfulthunk

+1

Tôi không hiểu tại sao (xml-> zipped: track: name text) sẽ hoạt động, nhưng (xml-> zipped: songs: track: name text) sẽ không hoạt động hoặc (xml-> zipped: name text) sẽ không hoạt động. Bạn không chắc chắn lý do tại sao bạn phải chỉ định một mức độ nhất định của các thẻ lồng nhau nhưng không phải là các thẻ khác. –

+0

@RyanMoore đó là một [dây kéo] (http://www.haskell.org/haskellwiki/Zipper), các khóa kéo có ngữ cảnh nhạy cảm ở chỗ chúng có nút hiện tại và bạn phải đưa cho họ các hướng dẫn truyền tải tương đối phù hợp với nút ngữ cảnh đó. Rõ ràng là nút bối cảnh mặc định là gốc có ý nghĩa. –

Các vấn đề liên quan