一、为什么使用XML
-
便于不同应用程序之间通信:XML作为一种平台和语言无关的数据格式,能让不同应用程序之间方便地交换信息。
-
便于不同平台之间通信:XML是纯文本格式,能够跨平台使用,如Windows、Linux等操作系统。
-
便于不同平台之间数据共享:由于XML文件基于文本格式,任何平台都能够读取和解析,保证了数据的共享和互操作性。
二、DOM读取
XML文件内容
当前解析类型 ocr real
代码示例 :
public void handlerResultXml(LinkedList<ReconResult> list, String xmlStr, String flag) {
try {
Document document = null;
// 检查并去掉XML前置BOM标记
if (xmlStr.startsWith("\uFEFF")) {
xmlStr = xmlStr.substring(1);
}
try {
document = DocumentHelper.parseText(xmlStr);
} catch (DocumentException e) {
System.out.println("XML解析失败");
return;
}
// 根据配置文件中字段顺序进行解析
int num = 0; // 用于区分MRZ信息和VIZ信息
for (String fieldName : fields.split("、")) {
String xpathExpression = "//*[@Name='" + fieldName + "']";
Node node = document.selectSingleNode(xpathExpression);
if (node != null) {
ReconResult reconResult = parseNode(node, fieldName, num, flag);
updateReconResultInList(list, reconResult, flag);
num++;
}
}
} catch (Exception e) {
System.out.println("解析XML出现未知异常");
}
}
private ReconResult parseNode(Node node, String fieldName, int num, String flag) {
ReconResult reconResult = new ReconResult();
reconResult.setIndex(Integer.parseInt(((DefaultElement) node).attribute("Index").getValue()));
reconResult.setOcrName(fieldName); // 保存原始识别结果中的名称
// 对字段进行重命名操作
reconResult.setName(getFieldName(fieldName, num));
String content = StringUtils.isEmpty(node.getText()) ? "" : cleanText(node.getText());
if (flag.equals("ocr")) {
reconResult.setContent(content);
} else if (flag.equals("real")) {
reconResult.setRealContent(content);
}
Attribute posNode = ((DefaultElement) node).attribute("Pos");
if (posNode != null) {
reconResult.setPosition(posNode.getValue());
}
if (reconResult.getIndex() == 10 || reconResult.getIndex() == 11 || reconResult.getIndex() >= 13) {
reconResult.setEditState(true);
}
return reconResult;
}
private String getFieldName(String fieldName, int num) {
switch (fieldName) {
case "MRZ1":
case "MRZ2":
return fieldName;
case "OCR MRZ":
return "MRZ(VIZ)";
case "出生地点拼音":
return "出生地点本国(VIZ)";
case "签发地点拼音":
return "签发地点本国(VIZ)";
case "监护人姓名":
return "母名(VIZ)";
case "国籍":
return "本国国籍(VIZ)";
default:
return num < 13 ? fieldName.replaceAll("[a-zA-Z]|\\(|\\)", "") + "(MRZ)" :
fieldName.replaceAll("[a-zA-Z]|\\(|\\)", "") + "(VIZ)";
}
}
private String cleanText(String text) {
return text.replaceAll("\r", "").replaceAll("\n", "").replaceAll("\t", "");
}
private void updateReconResultInList(LinkedList<ReconResult> list, ReconResult reconResult, String flag) {
ReconResult existingResult = list.stream()
.filter(o -> o.getName().equals(reconResult.getName()))
.findAny()
.orElse(null);
if (existingResult != null) {
// 当前集合中已经存在内容,修改对应的值和坐标
list.forEach(o -> {
if (o.getName().equals(reconResult.getName())) {
o.setPosition(reconResult.getPosition());
if (flag.equals("real")) {
o.setRealContent(StringUtils.isEmpty(reconResult.getRealContent()) ? "" : reconResult.getRealContent());
}
if (flag.equals("ocr")) {
o.setContent(StringUtils.isEmpty(reconResult.getContent()) ? "" : reconResult.getContent());
}
}
});
} else {
// 答案不存在的情况下该值为null,进行空值处理,减少前端判断
if (StringUtils.isEmpty(reconResult.getRealContent())) reconResult.setRealContent("");
list.add(reconResult);
}
}
封装示例
public String getXmlByResult(LinkedList<ReconResult> xmlHandelList, String flag) {
StringBuilder xml = new StringBuilder();
xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append("\r\n");
xml.append("<IDCardInfo>").append("\r\n");
// 将数据集合按照索引排序
List<ReconResult> sortedList = xmlHandelList.stream()
.sorted(Comparator.comparingInt(ReconResult::getIndex))
.collect(Collectors.toList());
int count = 0;
for (ReconResult reconResult : sortedList) {
if (reconResult.getIndex() == -1) continue;
// 开始创建Field标签
xml.append("\t").append("<Field Index=\"").append(reconResult.getIndex()).append("\" ");
// 添加Name和Pos属性
String fieldName = flag.equals("ocr") ? escapeXml(reconResult.getOcrName()) : escapeXml(getRealName(reconResult));
xml.append("Name=\"").append(fieldName).append("\" ");
if (flag.equals("ocr")) {
xml.append("Pos=\"").append(reconResult.getPosition()).append("\">");
// 添加内容
String content = reconResult.getContent();
xml.append("<![CDATA[").append(content != null ? content : "").append("]]>");
if (content != null) count++;
} else {
xml.append(">");
// 添加内容
String realContent = reconResult.getRealContent();
xml.append(realContent != null ? escapeXml(realContent) : "");
if (realContent != null) count++;
}
xml.append("</Field>").append("\r\n");
}
xml.append("</IDCardInfo>");
return count == 0 ? "" : xml.toString();
}
private String escapeXml(String input) {
if (input == null) return "";
return input.replaceAll("\"", """)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("'", "'")
.replaceAll("’", "'");
}
private String getRealName(ReconResult reconResult) {
String realName = reconResult.getRealName();
return StringUtils.isEmpty(realName) ? reconResult.getOcrName() : realName;
}