替换xml标签里的“&”“<”“>”为转义字符

原创
2012/04/26 22:36
阅读数 1.4W

我们的项目中需要获取Git的日志数据,用到git log命令进行日志的获取。Git没有像SVN那样,提供定义好的xml格式的日志文件。但是可以自己定义格式:git log --pretty=format:"your own format",然后我用自己写的xml标签加git提供的一些placeholder生成了类似于xml的日志文件。主要还是觉得xml文件比较方便解析。

然后发现这样生成的xml日志文件存在问题:日志的提交说明(message)是由用户填写的,那么用户就可能写入“&”“<”“>”这样的内容。众所周知xml里出现单独的这些字符是不合法的,该文件是不能被解析的。

在svn里,用户如果在提交说明里输入“&”“<”“>”,生成的xml日志文件会自动把它们转换成“&amp;”“&lt;”“&gt;“。但是git内部并不知道我定义的格式是xml的,那么也就不会自动转换。所以,我生成的git日志文件后,需要把提交说明<msg></msg>标签里的“&”“<”“>”替换为对应的转义字符。

 

主要的思想是用java.lang.String中的replaceAll(String regex, String replacement)函数进行替换。

查了java.util.regex.Patternjava.util.regex.Matcher两个类的文档。

java.util.regex.Pattern 组和捕获:

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

1     ((A)(B(C)))
2     \A
3     (B(C))
4     (C)

组零始终代表整个表达式。

java.util.regex.Matcher关于替换字符串:

替换字符串可能包含到以前匹配期间所捕获的子序列的引用:$g 每次出现时,都将被 group(g) 的计算结果替换。$ 之后的第一个数始终被视为组引用的一部分。如果后续的数可以形成合法组引用,则将被合并到 g 中。只有数字 '0' 到 '9' 被视为组引用的可能组件。例如,如果第二个组匹配字符串 "foo",则传递替换字符串 "$2bar" 将导致 "foobar" 被添加到字符串缓冲区。

所以我用了括号和$g来进行替换:

public void chartReplace(){
		String str2 = "<logentry revision='1'>" +
				"<msg>In this comment, I fixed a <bug>, and <added> file1&&file2.</msg>" +
				"</logentry>";
		System.out.println("original string: "+str2);
		
		//替换“&”:$1表示与(<msg>.*)的匹配子序列;$4表示与(.*</msg>)匹配的。
                     //&(?!amp;)表示匹配&而且后面不是amp;的字符串
		//"$1&amp;$3$4"得到的结果就是替换了<msg></msg>中的“&”为“&amp;”
		//由于每次只能替换掉一个“&”,所以循环执行替换,直到替换后与替换前的字符串相等。
		String str1 = "";
		while(!str2.equals(str1)){
			str1 = str2;
			str2 = str1.replaceAll("(<msg>.*)(&(?!amp;))(.*</msg>)", "$1&amp;$3");
		}
		System.out.println("firstly replace \"&\": "+str2);
		
		//替换“<”
		str1 = "";
		while(!str2.equals(str1)){
			str1 = str2;
			str2 = str1.replaceAll("(<msg>.*)(<)(.*</msg>)", "$1&lt;$3");
		}
		System.out.println("then replace \"<\": "+str2);
		
		//替换“<”
		str1 = "";
		while(!str2.equals(str1)){
			str1 = str2;
			str2 = str1.replaceAll("(<msg>.*)(>)(.*</msg>)", "$1&gt;$3");
		}
		System.out.println("finally replace \">\": "+str2);
	}

输出结果:

original string: <logentry revision='1'><msg>In this comment, I fixed a <bug>, and <added> file1&&file2.</msg></logentry>
firstly replace "&": <logentry revision='1'><msg>In this comment, I fixed a <bug>, and <added> file1&amp;&amp;file2.</msg></logentry>
then replace "<": <logentry revision='1'><msg>In this comment, I fixed a &lt;bug>, and &lt;added> file1&amp;&amp;file2.</msg></logentry>
finally replace ">": <logentry revision='1'><msg>In this comment, I fixed a &lt;bug&gt;, and &lt;added&gt; file1&amp;&amp;file2.</msg></logentry>

从结果可以看出达到了我想要的效果。由于没有在网上搜到相关的解决方案,也不知道该方法是不是常用的方法,效率怎么样。如果找到更好的方法,再继续更新。

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部