亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中的xml文件怎么利用正則表達式進行解析

發布時間:2020-12-02 17:15:20 來源:億速云 閱讀:246 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關Java中的xml文件怎么利用正則表達式進行解析,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

一、編寫Node類

Node對象是文檔解析的基礎,最終可以通過對象的不同屬性實現對文檔信息的訪問。

Node.java:

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class Node implements Serializable {
  // 可以對Node對象持久化保存
  private static final long serialVersionUID = 1L;
  private int id;
  // 節點類型
  private String title;
  // 節點內容
  private String text;
  // 節點屬性集合
  private Map<String, String> attributes = new HashMap<String, String>();
  // 子節點集合
  private List<Node> childNodes = new LinkedList<Node>();
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getTitle() {
    return title;
  }
  public void setTitle(String title) {
    this.title = title;
  }
  public Map<String, String> getAttribute() {
    return attributes;
  }
  public void setAttribute(Map<String, String> attribute) {
    this.attributes = attribute;
  }
  public String getText() {
    return text;
  }
  public void setText(String text) {
    this.text = text;
  }
  public List<Node> getChildNode() {
    return childNodes;
  }
  public void setChildNode(List<Node> childNode) {
    this.childNodes = childNode;
  }
  // 將屬性集合轉換成一條完整的字符串
  private String attrToString() {
    if (attributes.isEmpty()) {
      return "";
    }
    Iterator<Entry<String, String>> its = attributes.entrySet().iterator();
    StringBuffer buff = new StringBuffer();
    while (its.hasNext()) {
      Entry<String, String> entry = its.next();
      buff.append(entry.getKey() + "=\"" + entry.getValue() + "\" ");
    }
    return " " + buff.toString().trim();
  }
  // 輸出完整的節點字符串也用到了遞歸
  @Override
  public String toString() {
    String attr = attrToString();
    if (childNodes.isEmpty() && text == null) {
      return "<" + title + attr + "/>\n";
    } else if (childNodes.isEmpty() && text != null) {
      return "<" + title + attr + ">\n" + text + "\n" + "</" + title + ">\n";
    } else {
      StringBuffer buff = new StringBuffer();
      buff.append("<" + title + attr + ">\n");
      if (!text.isEmpty()) {
        buff.append(text + "\n");
      }
      for (Node n : childNodes) {
        buff.append(n.toString());
      }
      buff.append("</" + title + ">\n");
      return buff.toString();
    }
  }
}

二、創建接口

把文檔的讀取和分析抽象成接口方便今后替換實現。

過濾器:讀取文檔的字符流并刪除注釋的部分。這些信息通常是提供給人閱讀的,程序分析直接忽略。

XmlFilter.java:

/*
 * 過濾器的作用是刪除xml文件中不重要的部分。
 * 通常都是一些注釋性文字,不需要被機器解析。
 */
public interface XmlFilter {
  String filter();
  // 提供自定義正則表達式,識別符合過濾條件的字符串
  String filter(String[] regex);
}

解析器:將一個父節點解析成多條子節點的字符串。如果返回值為null,代表當前節點下不存在可以繼續解析的對象。

XmlParser.java:

import java.util.List;
/*
 * 解析器可以對一段完整的父節點字符串提供解析服務。
 * 將一條父節點的字符串解析成為多條子節點字符串
 */
public interface XmlParser {
  // 解析一段父節點,返回子節點字符串
  List<String> parser(String str);
}

三、根據接口編寫實現類

回車、換行、制表符以及各種注釋部分的內容都被刪除,簡化字符輸出。

SimpleXmlFilter.java:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class SimpleXmlFilter implements XmlFilter {
  private String text;
  // 常用的過濾正則表達式
  public final static String[] REG = { "\t", "<\\&#63;.*&#63;\\&#63;>", "<!.*&#63;>", "<%.*&#63;%>", "\\s{2,}" };
  // 讀取xml文檔返回字符串
  public SimpleXmlFilter(File file) throws IOException {
    BufferedReader in = new BufferedReader(new FileReader(file));
    StringBuffer buff = new StringBuffer();
    String temp = null;
    while ((temp = in.readLine()) != null) {
      buff.append(temp);
    }
    in.close();
    text = buff.toString().trim();
  }
  @Override
  public String filter() {
    return filter(REG);
  }
  @Override
  public String filter(String[] regex) {
    String result = text;
    for (String reg : regex) {
      result = result.replaceAll(reg, "");
    }
    return result;
  }
}

主要是通過正則表達式區分一個節點內部的子節點,考慮到節點的類型我將它們分為自閉合與非自閉合兩種類型。<title attributes .../>這樣的節點屬于自閉合類型,它們不包含子節點和text屬性,它們屬于文檔樹的葉子節點。<title attributes ...>text ...</title>這樣的節點屬于非自閉合類型,它們屬于文檔樹的分支節點。

SimpleXmlParser.java:

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SimpleXmlParser implements XmlParser {
  @Override
  public List<String> parser(String text) {
    List<String> childrenDocs = new ArrayList<String>();
    // 捕獲根節點中間的文本
    Pattern p = Pattern.compile("<.*&#63;>(.*)</.*&#63;>");
    Matcher m = p.matcher(text);
    if (m.matches()) {
      String inner = m.group(1);
      // 匹配節點字符串
      p = Pattern.compile("<(.*&#63;)>");
      m = p.matcher(inner);
      while (m.find()) {
        String s1 = m.group(1);
        // 如果節點以/結尾,代表此節點不包含子節點
        if (s1.endsWith("/")) {
          childrenDocs.add(m.group());
          // 如果節點既不以/開頭,也不以/結尾則表示需要查找對應的閉合節點
        } else if (!s1.startsWith("/") && !s1.endsWith("/")) {
          // 計算起始字符數
          int start = m.end() - m.group().length();
          // 如果捕獲到未閉合節點則index++,如果捕獲到閉合節點則index--
          int index = 1;
          while (m.find()) {
            String s2 = m.group(1);
            if (!s2.startsWith("/") && !s2.endsWith("/")) {
              index++;
            } else if (s2.startsWith("/")) {
              index--;
            }
            // 找到符合條件的閉合節點則循環終止
            if (index == 0) {
              break;
            }
          }
          // 計算結束字符數
          int end = m.end();
          // 截取對應字符串
          childrenDocs.add(inner.substring(start, end));
        }
      }
    }
    return childrenDocs;
  }
}

四、編寫NodeBuilder類

根據過濾器和解析器獲取Node節點各屬性的值。

NodeBuilder.java:

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// 生成Node
public class NodeBuilder {
  private Node root = new Node();
  private XmlParser parser;
  private XmlFilter filter;
  // 提供合適的過濾器和解析器
  public NodeBuilder(XmlParser parser, XmlFilter filter) {
    this.parser = parser;
    this.filter = filter;
  }
  public Node getRoot(String... regex) {
    String str = null;
    if (regex.length == 0) {
      str = filter.filter();
    } else {
      str = filter.filter(regex);
    }
    buildNodeTree(str, root);
    return root;
  }
  // 設置節點類型
  private void buildNodeTitle(String str, Node n) {
    Pattern p = Pattern.compile("<.*&#63;>");
    Matcher m = p.matcher(str);
    if (m.find()) {
      String temp = m.group();
      String s = temp.substring(1, temp.length() - 1).split(" ")[0];
      if (s.endsWith("/")) {
        n.setTitle(s.substring(0, s.length() - 1));
      } else {
        n.setTitle(s.split(" ")[0]);
      }
    }
  }
  // 設置節點屬性集合
  private void buildNodeAttribute(String str, Node n) {
    Pattern p = Pattern.compile("<.*&#63;>");
    Matcher m = p.matcher(str);
    if (m.find()) {
      String temp = m.group();
      String s = temp.substring(1, temp.length() - 1);
      // 匹配字符串
      p = Pattern.compile("(\\S*)=\"(.*&#63;)\"");
      m = p.matcher(s);
      while (m.find()) {
        String key = m.group(1).trim();
        String value = m.group(2).trim();
        n.getAttribute().put(key, value);
      }
      // 匹配數字
      p = Pattern.compile("(\\S*)=(-&#63;\\d+(\\.\\d+)&#63;)");
      m = p.matcher(s);
      while (m.find()) {
        String key = m.group(1).trim();
        String value = m.group(2).trim();
        n.getAttribute().put(key, value);
      }
    }
  }
  // 設置節點內容,節點的內容是刪除了所有子節點字符串以后剩下的部分
  private void buildNodeText(String str, Node n) {
    Pattern p = Pattern.compile("<.*&#63;>(.*)</.*&#63;>");
    Matcher m = p.matcher(str);
    List<String> childrenDocs = parser.parser(str);
    if (m.find()) {
      String temp = m.group(1);
      for (String s : childrenDocs) {
        temp = temp.replaceAll(s, "");
      }
      n.setText(temp.trim());
    }
  }
  // 通過遞歸生成完整節點樹
  private void buildNodeTree(String str, Node n) {
    buildNodeTitle(str, n);
    buildNodeAttribute(str, n);
    buildNodeText(str, n);
    // 如果存在子節點則繼續下面的操作
    if (!parser.parser(str).isEmpty()) {
      // 對每一個子節點都應該繼續調用直到遞歸結束
      for (String temp : parser.parser(str)) {
        Node child = new Node();
        buildNodeTitle(temp, child);
        buildNodeAttribute(temp, child);
        buildNodeText(temp, child);
        n.getChildNode().add(child);
        buildNodeTree(temp, child);
      }
    }
  }
}

五、測試

編寫xml測試文件

測試文件:

<package>
  <!-- 這里是注釋1 -->
  package message before!
  <class id="exp1" path="www.sina.com"/>
  <class id="exp2">
    <class id="inner">
      class message inner.
    </class>
  </class>
  package message middle!
  <!-- 這里是注釋2 -->
  <class id="exp3">
    <method id="md" name="setter" order=1>
      <!-- 這里是注釋3 -->
      <!-- 這里是注釋4 -->
      <para ref="String"/>
      <para ref="exp1">
        method message inner!
      </para>
    </method>
  </class>
  package message after!
</package>

編寫測試類

Demo.java:

import java.io.File;
import java.io.IOException;
public class Demo {
  public static void main(String[] args) {
    File f = new File("xxx");
    XmlFilter filter = null;
    try {
      filter = new SimpleXmlFilter(f);
    } catch (IOException e) {
      e.printStackTrace();
    }
    XmlParser parser = new SimpleXmlParser();
    NodeBuilder builder = new NodeBuilder(parser, filter);
    Node node = builder.getRoot();
    System.out.println(node);
  }
}

輸出:

<package>
package message before!package message middle!package message after!
<class path="www.sina.com" id="exp1"/>
<class id="exp2">
<class id="inner">
class message inner.
</class>
</class>
<class id="exp3">
<method name="setter" id="md" order="1">
<para ref="String"/>
<para ref="exp1">
method message inner!
</para>
</method>
</class>
</package>

關于Java中的xml文件怎么利用正則表達式進行解析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

化州市| 广东省| 长汀县| 弥勒县| 全州县| 巍山| 樟树市| 建始县| 东乡县| 水富县| 辽阳县| 眉山市| 营口市| 泰兴市| 汉源县| 邢台市| 正镶白旗| 龙山县| 鄂州市| 上林县| 淮阳县| 株洲县| 无锡市| 南丰县| 富裕县| 山东| 嵩明县| 炎陵县| 郯城县| 抚顺市| 吉隆县| 光泽县| 镇坪县| 朝阳县| 江津市| 静乐县| 来宾市| 巴楚县| 通榆县| 中山市| 嵩明县|