2017-02-15 11 views
-2

Я пытаюсь скрыть все вхождения AccountNumber в моем ответе на код XML. AccountNumber имеет 16 цифр, и я хочу скрыть первые 12 цифр и сохранить последние четыре.regex для маскировки всех номеров счетов в XML до последних четырех цифр

XML ответ:

<ns2:PaymentMethod> 
    <CCInfo xmlns=""> 
      <AccountType>sdaj</AccountType> 
      <AccountNumber>123456789</AccountNumber> 
      <AccountName>sdfsad</AccountName> 
      <ExpirationMonth>sdaf</ExpirationMonth> 
      <ExpirationYear>afgds</ExpirationYear> 
    </CCInfo> 
    </ns2:PaymentMethod> 
    <ns2:PaymentMethod> 
    <CCInfo xmlns=""> 
      <AccountType>kyfkuk</AccountType> 
      <AccountNumber>098765432123987</AccountNumber> 
      <AccountName>hjvkv</AccountName> 
      <ExpirationMonth>gfdgh</ExpirationMonth> 
      <ExpirationYear>tdjk</ExpirationYear> 
    </CCInfo> 
    </ns2:PaymentMethod> 

Ниже мой Java-код:

String accountNumberPatternString ="<AccountNumber>(^.{12})"; 
Pattern accountNumberPattern = Pattern.compile(accountNumberPatternString); 
Matcher matcher = accountNumberPattern.matcher(data); 
String maskedResult = matcher.replaceAll("<AccountNumber>*******"); 

Я ожидаю, что результат как:

<AccountNumber>************3456</AccountNumber> 

, но я получаю результат как :

<AccountNumber>123456789</AccountNumber> 
+1

почему это ''^в шаблоне? –

+0

Одним из решений было бы извлечение AN из xml. После этого вы можете использовать: String.format ("% 1 $" + AN.length() + "s", AN.subString (13,15) .replace ("", "*"); – Tom

+0

надеюсь вы используете действительный метод для преобразования потока xml в String, чтобы не повредить данные в этом процессе. – jtahlborn

ответ

1

Я уверен, что вы знаете о dangers of parsing XML with regex, но давайте игнорировать, что на данный момент.

на основе ваших обновленных требований, что длина номера счета может меняться, я бы предложил использовать Matcher.appendReplacement, например, так:

Pattern p = Pattern.compile("(?<=<AccountNumber>)\\d*(?=\\d{4})"); 
    Matcher m = p.matcher(data); 
    StringBuffer maskedResult = new StringBuffer(); 
    while (m.find()) { 
     String thisMask = m.group(0).replaceAll(".", "*"); 
     m.appendReplacement(maskedResult, thisMask); 
    } 
    m.appendTail(maskedResult); 
    System.out.println(maskedResult.toString()); 

Примечание В приведенном выше примере я использовал положительный назад '(?<=) к идентифицируйте начало номера счета, затем положительный прогноз (?=), чтобы сохранить четыре цифры.

Наконец, вот более надежная версия, которая обрабатывает номера счетов с букв, пробелов и/или штрихами, такие как "<AccountNumber> 123 456-78901FFA-56C </AccountNumber>":

Pattern p = Pattern.compile("(?<=<AccountNumber>)([-\\s\\w]*)((?:[a-zA-Z0-9][-_\\s]*){4})"); 
    Matcher m = p.matcher(data); 
    StringBuffer maskedResult = new StringBuffer(); 
    while (m.find()) { 
     String thisMask = m.group(1).replaceAll("[^-_\\s]", "*"); 
     m.appendReplacement(maskedResult, thisMask + "$2"); 
    } 
    m.appendTail(maskedResult); 
    System.out.println(maskedResult.toString()); 
+0

Я получаю следующую ошибку в строке m.appendReplacement (maskedResult, thisMask); Метод appendReplacement (StringBuffer, String) в типе Matcher не применим для аргументов (StringBuilder, String) – eureka19

+1

@ eureka19 О, извините, извините. Думаю, вам нужно использовать StringBuffer, а не StringBuilder. Я обновил ответ. –

2

^ неправ. И если у вас есть только номера, вы должны также сопоставлять номера только с \d. И скобки () не нужны.

https://regex101.com/r/Uu6qTR/1

<AccountNumber>\d{12} 
+0

Когда я использую String accountNumberPatternString = " \ d {12}", я получаю сообщение об ошибке: Недопустимая escape-последовательность (допустимые - \ b \ t \ n \ f \ r \ "\ '\\) – eureka19

+2

Ну ... конечно ... вам нужно удвоить escape-обратную косую черту, потому что она внутри строки. –

+1

@FlorianPeschka eureka19, попробуйте использовать: \\ d {12} – Sebastien