繁体   English   中英

替换匹配的 XML 标签的内容

[英]Replace content of matching XML tags

我有一个 XML 字符串。 我想替换包含某些标签的所有文本内容。

例如:

案例一:

  • 输入:
     <newPassword>SOME_NEW_PASSWORD</newPassword> <oldPasscode>SOME_OLD_PASSWORD</oldPasscode>
  • Output:
     <newPassword>**HIDDEN**</newPassword> <oldPasscode>**HIDDEN**</oldPasscode>

示例案例 2:

  • 输入:
     <password>SOME_NEW_CODE</password> <passcode>SOME_OLD_CODE</passcode>
  • Output:
     <password>**HIDDEN**</password> <passcode>**HIDDEN**</passcode>

因此,如果 XML 标签包含passwordpasscode ,则将其内容替换为**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后跟wordcode的模式(假设<>是密码的有效字符)

<([^<>\s]*pass(?:word|code)[^<>\s]*)>.*?</\1>
  • <匹配<
  • ([^<>\s]*pass(?:word|code)[^<>\s]*)< >或空白字符以外的可选字符之间匹配passwordpasscode
  • >匹配>
  • .*? 匹配尽可能少的字符
  • </\1>匹配</后跟对第 1 组的反向引用(匹配元素名称)和>

请参阅Java 演示或正则表达式演示

在替换中使用**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}>");
  • 在 Java Regex (?<tagName>MATCH_ME)定义了一个命名组匹配MATCH_ME
  • 在 Java 正则表达式\\k<tagName>指的是已经命名的组(这里MATCH_ME
  • 在 Java 中,替换${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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM