XML解析小坑记录[正则表达式解析]

一、问题描述

在做 SSO 单点登录时( 认证中为CAS服务对接 )。在完成对用户ticket票根校验后,返回了用户信息有关 XML 数据片段,例如下:

xml 复制代码
<cas:serviceResponse xmlns:cas="http://www.xxx.xx/xx/cas">
  <cas:authenticationSuccess>
    <cas:user>200161</cas:user>
    <cas:username>张三</cas:username>
    <cas:usertype>TEACHER</cas:usertype>
  </cas:authenticationSuccess>
</cas:serviceResponse>

获取到CAS 认证中心返回的数据后,通过 Java中的 PatternMatcher 对象来获取XML 中的数据!

Pattern 和 Matcher 是用于处理正则表达式的两个主要类。

它们的主要作用和用途如下:

  1. Pattern 类
  • 作用:Pattern类是用于编译正则表达式的类。它代表一个编译后的正则表达式,可以对输入的字符串执行匹配操作。
  • 创建:通过调用静态方法 Pattern.compile() 来创建 Pattern 对象,并传入需要的正则表达式作为参数。
  1. Matcher 类
  • 作用:Matcher 类是对输入字符串进行匹配和搜索的类。它与 Pattern 对象一起使用,用于执行匹配操作。
  • 创建:通过调用 Pattern 对象的 matcher 方法创建 Matcher 对象,并传入需要匹配的字符串。
java 复制代码
// 解析XML数据,获取指定信息
Pattern pt = Pattern.compile("<cas:user>(.*)</cas:user>");
Matcher matcher = pt.matcher(resultXml);
while (matcher.find()){
    group0 = matcher.group(0).trim();
    group1 = matcher.group(1).trim();
}

​ 上面通过 Pattern 和 **Matcher **来解析出用户信息,但是使用到了 matcher.group(0) 获取的用户信息! 导致后续操作(我的后续操作是拿到的用户信息进行特定的加密后封装一个重定向路径)中使用获取到的用户信息一直失败,也没找到原因!!

  • 后面找到问题所在:使用 group(n) 方法获取匹配的内容:group(0) 返回整个匹配的部分,group(1) 返回第一个括号内的内容 !

这里至于为什么没有发现 通过 matcher.group(0) 和 matcher.group(1) 获取到的值不一样! 是因为我将这两值都直接返回到视图中渲染了,但在视图中展示的内容 他们是一样的!!

二、复现坑

controller 层代码:

java 复制代码
package com.example.gsxy_sso_u8cloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName : XmlBugController
 * @Description : 测试解析XML文件时出现的坑!
 * @Author : AD
 */

@RestController
@RequestMapping("/xmlbug")
public class XmlBugController {

    /**
     * Description: 模拟解析XML文件的接口
     *  通过 group(0) / group(1)  对比从XML数据中提取的值!
     *
     * @param
     * @return java.lang.String
     * @date 2024-10-24
    */
    @GetMapping("/getXmlInfo")
    public String getXmlInfo(HttpServletRequest request, HttpServletResponse response) throws IOException {


        // 模拟Cas认证校验成功后,返回的用户信息数据 resultXml
        String resultXml = "<cas:serviceResponse xmlns:cas=\"http://www.xxx.xxx/xx/cas\"> "+
                            " <cas:authenticationSuccess> "+
                            " <cas:user>200161</cas:user> "+
                            " <cas:username>张三</cas:username> "+
                            " <cas:usertype>TEACHER</cas:usertype> "+
                           " </cas:authenticationSuccess> "+
                         " </cas:serviceResponse> ";

        /**
         * 定于两个接收解析数据的对象 分别接收 group(0) 和 group(1)
         * */
        String group0 = "";
        String group1 = "";

        // 解析XML数据,获取指定信息
        Pattern pt = Pattern.compile("<cas:user>(.*)</cas:user>");
        Matcher matcher = pt.matcher(resultXml);
        while (matcher.find()){
            group0 = matcher.group(0).trim();
            group1 = matcher.group(1).trim();
        }
        System.out.println("从XML中解析出来的 group0 = " + group0);
        System.out.println("从XML中解析出来的 group1 = " + group1);

        /*
        // 设置响应内容类型为 XML
        response.setContentType("application/xml;charset=UTF-8");
        // 创建 XML 内容
        String xmlContent = "<cas:user>200161</cas:user>";
        // 输出 XML 内容
        response.getWriter().write(xmlContent);
        */

        return "group0 = "+ group0+" \t\n"+
                "group1 = "+ group1+" \t\n";
    }
}

访问controller 接口查看响应数据:

可以看出在浏览器中渲染出来的数据,显式的结果是一样的!!!~~ 所以这里就导致我没发现端倪( 因为远程服务器的配置特殊 )!!!

但是我们可以通过 页面元素 和 网络响应中看出他们的不同之处!

  • 页面元素:
  • 网络响应:

为什么是使用 group(1) 而不是 group(0) 呢?

在使用正则表达式时,group(0) 和 group(1) 的含义是不同的:

  1. group(0):

○ 返回整个匹配的字符串。这是正则表达式匹配结果的完整文本,包括所有的匹配内容。

○ 在你的例子中,group(0) 将返回整个匹配的内容,例如:"cas:user200161</cas:user>"。

  1. group(1):

○ 返回第一个捕获组中的内容。当你在正则表达式中使用括号 () 来创建捕获组时,你可以通过 group(1) 访问第一个捕获组所匹配的内容。

○ 在你的例子中,group(1) 将返回被 cas:user 标签包围的内容,即实际的用户 ID,例如 "200161"。

相关推荐
直视太阳11 分钟前
springboot+easyexcel实现下载excels模板下拉选择
java·spring boot·后端
Code成立17 分钟前
《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》第2章 Java内存区域与内存溢出异常
java·jvm·jvm内存模型·jvm内存区域
一 乐34 分钟前
实验室预约|实验室预约小程序|基于Java+vue微信小程序的实验室预约管理系统设计与实现(源码+数据库+文档)
java·数据库·微信小程序·小程序·毕业设计·论文·实验室预约小程序
程序媛学姐37 分钟前
SpringRabbitMQ消息模型:交换机类型与绑定关系
java·开发语言·spring
努力努力再努力wz44 分钟前
【c++深入系列】:类与对象详解(中)
java·c语言·开发语言·c++·redis
兰亭序咖啡1 小时前
学透Spring Boot — 009. Spring Boot的四种 Http 客户端
java·spring boot·后端
独行soc1 小时前
2025年渗透测试面试题总结- 某四字大厂面试复盘扩展 一面(题目+回答)
java·数据库·python·安全·面试·职场和发展·汽车
早上好啊! 树哥1 小时前
常见的文件加密方式之【异或加密】,代入原理看例子,帮助更好的理解。
android·java·junit
兰亭序咖啡2 小时前
学透Spring Boot — 018. 优雅支持多种响应格式
java·spring boot·后端
小雨凉如水2 小时前
docker 常用命令
java·docker·eureka