Clojure:解析XML,首先删除头尾线

时间:2016-05-23 09:11:09

标签: java clojure text-processing

我今天遇到一个我无法解决的问题。

上下文

我有一个带有这种输入的目录:

<catalogue>
  <produit>
    <nom>mince</nom>
    <sku>25</sku>
    <criterias>
      <criteria>65</criteria>
      <criteria>25</criteria>
    </criterias>
  </produit>
  <produit>
    <nom>gros</nom>
    <sku>56</sku>
    <criterias>
      <criteria>35</criteria>
      <criteria>8</criteria>
    </criterias>
  </produit>
</catalogue>

我想将其转换为EDN。事实上,我成功获得了样本数据;这是第一步(然后我只进行延迟处理):

(defn catalog-fr-to-edn []
  (let [content (slurp "catalog-fr.xml")]
    (->> (xml/parse-str content)
         (into {}))))

但是,正如你所看到的 - 也许我会错过一些东西 - 但我没有看到从这个库解析XML的其他方法,除了将所有内容作为STR。问题是我有700 MB的数据!

所以我想要更好的东西

1)首先删除“目录”行

  <produit>
    <nom>mince</nom>
    <sku>25</sku>
    <criterias>
      <criteria>65</criteria>
      <criteria>25</criteria>
    </criterias>
  </produit>
  <produit>
    <nom>gros</nom>
    <sku>56</sku>
    <criterias>
      <criteria>35</criteria>
      <criteria>8</criteria>
    </criterias>
  </produit>

因此,我实际上有N个“XML”文件,它们对应于N个产品。

2)逐行写记录,如

{:sku 25 ...}

问题

我认为第一步是好的(我没有看到文件的尾部,标题是好的)。他是第一部分的脚本

(defn remove-lines [input nskip]
  (let [path (->> (decompose-filepath input)
                  (last)
                  (str "qsdqsdqsdqsd."))]
    (with-open [rdr (io/reader input)]
      (with-open [wrt (io/writer path)]
        (loop [n nskip]
          (let [line (.readLine rdr)]
            (cond (nil? line)
                    nil
                  (and (not (nil? line)) (not (empty? (re-find #"<\\catalogue>.*" line))))
                    nil
                  :else
                    (cond (pos? n)
                            (recur (dec n))
                          :else
                            (do (doto wrt (.write line) (.newLine))
                                          (recur n))))))))
    (io/delete-file input)
    (rename-file path input)))

现在我想做第二步,但我不知道如何做到这一点。我可以为1个产品做这个,但我不知道如何在文件中保存位置。

XML解析是可以的,所以让我说我只想要那样的行作为输出(我删除可见性换行符):

"<produit><nom>mince</nom><sku>25</sku><criterias><criteria>65</criteria><criteria>25</criteria></criterias></produit>"

即。阅读内容直到达到,阅读阅读文章,写下来,然后跳到下一篇文章。

我需要其他Java类吗?如果它更好,我可以使用Java代码。

或者我想错过clojure.data.xml图书馆的内容?

由于

1 个答案:

答案 0 :(得分:0)

它有点幼稚,它是Java代码,但它很容易移植到Clojure。因为我不需要它,所以我没有深入尝试

包文件;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CatalogReader {

    public static void processFile (String input, String output) throws FileNotFoundException {

        try {

            // File input
            FileInputStream fstream = new FileInputStream(input);   
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader (new InputStreamReader(in));

            //File output
            File out = new File(output);
            FileOutputStream fos = new FileOutputStream(out);
            BufferedWriter bw = new BufferedWriter (new OutputStreamWriter(fos));

            String line;
            String product = "";

            Pattern pat = Pattern.compile("</catalogue>");
            Matcher mat;

            while ((line = br.readLine()) != null) {

                mat = pat.matcher(line);

                while (!mat.find()) {

                    product.concat(line);

                }

                bw.write(product);
                bw.newLine()
                product = "";

            }

            br.close();
            bw.close();
        }

        catch (IOException e) { System.err.println("Error: " + e.getMessage());}
    }

}