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"。

相关推荐
尘浮生25 分钟前
Java项目实战II基于微信小程序的南宁周边乡村游平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·微信小程序·小程序·maven
耀耀_很无聊4 小时前
第1章 初识SpringMVC
java·spring·mvc
麻衣带我去上学4 小时前
Spring源码学习(一):Spring初始化入口
java·学习·spring
东阳马生架构4 小时前
MySQL底层概述—1.InnoDB内存结构
java·数据库·mysql
手握风云-5 小时前
数据结构(Java版)第一期:时间复杂度和空间复杂度
java·数据结构
坊钰5 小时前
【Java 数据结构】时间和空间复杂度
java·开发语言·数据结构·学习·算法
飞升不如收破烂~6 小时前
Redis的String类型和Java中的String类在底层数据结构上有一些异同点
java·数据结构·redis
苹果酱05676 小时前
windows安装redis, 修改自启动的redis服务的密码
java·开发语言·spring boot·mysql·中间件
feilieren6 小时前
信创改造 - TongRDS 替换 Redis
java·spring boot·后端
Allen Bright6 小时前
Jedis连接池的操作
java·redis