[英]Replace content of matching XML tags
我有一个 XML 字符串。 我想替换包含某些标签的所有文本内容。
例如:
案例一:
<newPassword>SOME_NEW_PASSWORD</newPassword> <oldPasscode>SOME_OLD_PASSWORD</oldPasscode>
<newPassword>**HIDDEN**</newPassword> <oldPasscode>**HIDDEN**</oldPasscode>
示例案例 2:
<password>SOME_NEW_CODE</password> <passcode>SOME_OLD_CODE</passcode>
<password>**HIDDEN**</password> <passcode>**HIDDEN**</passcode>
因此,如果 XML 标签包含password
或passcode
,则将其内容替换为**HIDDEN**
。
我尝试使用正则表达式并替换所有出现的情况,如下所示:
String MASK = "**HIDDEN**";
Pattern pattern = Pattern.compile("(?i)([^>])(?=<\/\wpass[word|code]\w*>)", Pattern.CASE_INSENSITIVE);
atcher matcher = pattern.matcher("<password>SOME_NEW_CODE</password><passcode>SOME_OLD_CODE</passcode>");
boolean matchFound = matcher.find();
if (matchFound) {
System.out.println(matcher.replaceAll(MASK));
}
output 即将推出: <newPassword>**HIDDEN****HIDDEN**</newPassword>
它替换了两次。
在您的模式[word|code]
是一个字符 class 匹配列出的字符之一。 如果您想匹配单词或代码,您可以使用替换(?:word|code)
匹配pass
后跟word
或code
的模式(假设<
和>
是密码的有效字符)
<([^<>\s]*pass(?:word|code)[^<>\s]*)>.*?</\1>
<
匹配<
([^<>\s]*pass(?:word|code)[^<>\s]*)
在<
>
或空白字符以外的可选字符之间匹配password
或passcode
>
匹配>
.*?
匹配尽可能少的字符</\1>
匹配</
后跟对第 1 组的反向引用(匹配元素名称)和>
在替换中使用**HIDDEN**
在括号<$1>**HIDDEN**</$1>
中捕获组 1 的值之间
请注意,这与此特定格式的 xml 元素匹配。 它不考虑任何结构的有效性。
String regex = "<([^<>\\s]*pass(?:word|code)[^<>]*)>.*?</\\1>";
String string = "<newPassword>SOME_NEW_PASSWORD</newPassword>\n"
+ "<oldPasscode>SOME_OLD_PASSWORD</oldPasscode>\n"
+ "<password>SOME_NEW_CODE</password>\n"
+ "<passcode>SOME_OLD_CODE</passcode>";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(string);
System.out.println(matcher.replaceAll("<$1>**HIDDEN**</$1>"));
Output
<newPassword>**HIDDEN**</newPassword>
<oldPasscode>**HIDDEN**</oldPasscode>
<password>**HIDDEN**</password>
<passcode>**HIDDEN**</passcode>
如果标签中只能有单词字符,而密码中没有<
或>
:
<(\w*pass(?:word|code)\w*)>[^<>]*</\1>
如果您需要使用其他标签,可以创建一个通用方法来执行此替换。 它可以像这样实现。
public String replaceTextBetweenTag(
final String input,
final String tag,
final String mask
) {
final String openingTag = String.format("<%s>", tag);
final String endTag = String.format("</%s>", tag);
return input.replaceAll(String.format("(%s)[^&]*(%s)",openingTag,endTag), openingTag + mask + endTag);
}
如果有多个需要替换的文本,可以这样使用
public String replaceTextBetweenTags(
final String input,
final List<String> tags,
final String mask
) {
String newOutput = input;
for(final String tag : tags){
newOutput = replaceTextBetweenTag(input, tag, mask);
}
return newOutput;
}
所以在你的情况下,简单的解决方案是
replaceTextBetweenTags("<newPassword>SOME_NEW_PASSWORD</newPassword>\n" +
"<oldPasscode>SOME_OLD_PASSWORD</oldPasscode>",
List.of("newPassword", "oldPasscode"),
"**HIDDEN**"
);
首先,您不想将正则表达式用于基于 XML 标签(当然包括 HTML)的任何内容。 在此处阅读更多信息并在此处输入链接描述。
满足该行为的最简单的 Regex 可能如下所示( Regex101的演示,包括替换):
<(?<tagName>[a-z]*[Pp]ass(?:code|word))>([^<]*)<\/\k<tagName>>
因此,在 Java 中,最小且可重现的样本可能如下所示:
String xml = "<newPassword>SOME_NEW_PASSWORD</newPassword>" +
"<oldPasscode>SOME_OLD_PASSWORD</oldPasscode>" +
"<password>SOME_NEW_CODE</password>" +
"<passcode>SOME_OLD_CODE</passcode>" +
"<nope>VALUE</nope>";
String hidden = xml.replaceAll(
"<(?<tagName>[a-z]*[Pp]ass(?:code|word))>[^<]*<\\/\\k<tagName>>",
"<${tagName}>**HIDDEN**<\\/${tagName}>");
或者(假设xml
变量存在):
String xml = // your xml
String regex = "<(?<tagName>[a-z]*[Pp]ass(?:code|word))>[^<]*<\\/\\k<tagName>>";
Pattern pattern = Pattern.compile(regex);
String hidden = pattern
.matcher(xml)
.replaceAll("<${tagName}>**HIDDEN**<\\/${tagName}>");
(?<tagName>MATCH_ME)
定义了一个命名组匹配MATCH_ME
\\k<tagName>
指的是已经命名的组(这里MATCH_ME
)${tagName}
指的是从正则表达式中捕获的命名组。 如果您漂亮地打印 output,结果如下所示(我使用nope
元素来演示保持原始值):
<newPassword>**HIDDEN**</newPassword>
<oldPasscode>**HIDDEN**</oldPasscode>
<password>**HIDDEN**</password>
<passcode>**HIDDEN**</passcode>
<nope>VALUE</nope>
注意:请记住,您可能需要根据 Regex 模式的严格程度进行一些修改。 如果可能,请使用适当的 XML 解析器。
您的 RegEx 只是缺少几个基数:
([^>])+(?=<\/\w*pass(word|code)\w*)
^ ^ ^
(?i)([^>]+)(?=<\/\w*pass(?:code|word)\w*>)
感谢@oliver_t 和@Nikolas。 我已从您的正则表达式中获取参考。 上面的正则表达式按预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.