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

咱们的项目中须要获取Git的日志数据,用到git log命令进行日志的获取。Git没有像SVN那样,提供定义好的xml格式的日志文件。可是能够本身定义格式:git log --pretty=format:"your own format",而后我用本身写的xml标签加git提供的一些placeholder生成了相似于xml的日志文件。主要仍是以为xml文件比较方便解析。java

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

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

 

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

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

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

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

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

组零始终表明整个表达式。日志

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

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

因此我用了括号和$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>

从结果能够看出达到了我想要的效果。因为没有在网上搜到相关的解决方案,也不知道该方法是否是经常使用的方法,效率怎么样。若是找到更好的方法,再继续更新。

相关文章
相关标签/搜索