Регулярное выражение, соответствует содержимому определенного тега XML, но без самого тега - PullRequest
2 голосов
/ 11 февраля 2011

Я бьюсь головой об этом регулярном выражении целый день.

Задача выглядит просто, у меня есть несколько имен тегов XML, и я должен заменить (замаскировать) их содержимое.

Например

<Exony_Credit_Card_ID>242394798</Exony_Credit_Card_ID>

Должен стать

<Exony_Credit_Card_ID>filtered</Exony_Credit_Card_ID>

Существует несколько таких тегов с разными именами

Как мне сопоставить любой текст внутри, но без совпадения с самим тегом?

РЕДАКТИРОВАТЬ : Я должен уточнить еще раз. Группировка, а затем использование группы, чтобы избежать замены текста внутри, не работает в моем случае, потому что, когда я добавляю другие теги в выражение, номер группы отличается для последующих совпадений. Например:

"(<Exony_Credit_Card_ID>).+(</Exony_Credit_Card_ID>)|(<Billing_Postcode>).+(</Billing_Postcode>)"

replaceAll на строку "$1filtered$2" не работает, потому что когда регулярное выражение соответствует Billing_Postcode, его группы равны 3 и 4 вместо 1 и 2

Ответы [ 5 ]

6 голосов
/ 11 февраля 2011
String resultString = subjectString.replaceAll(
    "(?x)    # (multiline regex): Match...\n" +
    "<(Exony_Credit_Card_ID|Billing_Postcode)> # one of these opening tags\n" +
    "[^<>]*  # Match whatever is contained within\n" +
    "</\\1>  # Match corresponding closing tag",
    "<$1>filtered</$1>");
1 голос
/ 11 февраля 2011

В вашей ситуации я бы использовал это:

(?<=<(Exony_Credit_Card_ID|tag1|tag2)>)(\\d+)(?=</(Exony_Credit_Card_ID|tag1|tag2)>)

И затем заменил бы совпадения на filtered, так как теги исключались из возвращенного совпадения.Поскольку ваша цель - скрыть конфиденциальные данные, лучше быть в безопасности и использовать «агрессивное» сопоставление, пытаясь сопоставить как можно больше конфиденциальных данных, даже если иногда это не так.

Возможно, вам придется настроитьсопоставление содержимого тега (\\d+), если данные содержат другие символы, такие как пробелы, косые черты, тире и т. д.

0 голосов
/ 11 февраля 2011

Я знаю, что вы сказали, что полагаться на номера групп не подходит в вашем случае ... но я не могу понять, как это сделать.Не могли бы вы использовать что-то вроде:

xmlString.replaceAll("<(Exony_Credit_Card_ID|tag2|tag3)>([^<]+)</(\\1)>", "<$1>filtered</$1>");

?Это работает с основными образцами, которые я использовал в качестве теста.

edit: просто для разложения:

"<(Exony_Credit_Card_ID|tag2|tag3)>" + // matches the tag itself
"([^<]+)" + // then anything in between the opening and closing of the tag
"</(\\1)>" // and finally the end tag corresponding to what we matched as the first group (Exony_Credit_Card_ID, tag1 or tag2)

"<$1>" + // Replace using the first captured group (tag name)
"filtered" + // the "filtered" text
"</$1>" // and the closing tag corresponding to the first captured group
0 голосов
/ 11 февраля 2011

Я бы использовал что-то вроде этого:

private static final Pattern PAT = Pattern.compile("<(\\w+)>(.*?)</\\1>");

private static String replace(String s, Set<String> toReplace) {
    Matcher m = PAT.matcher(s);
    if (m.matches() && toReplace.contains(m.group(1))) {
        return '<' + m.group(1) + '>' + "filtered" + "</" + m.group(1) + '>';
    }
    return s;
}
0 голосов
/ 11 февраля 2011

Я не отлаживал этот код, но вы должны использовать что-то вроде этого:

Pattern p = Pattern.compile("<\\w+>([^<]*)<\\w+>");
Matcher m = p.matcher(str);
if (m.find()) {
    String tagContent = m.group(1);
}

Я надеюсь, это хорошее начало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...