2016-04-06 5 views
1

Ich brauche ein Code-Schnipsel, die alle Werte von Tags umgeben in einem String in Java und geben sie als String-Array zurück, wenn die Namen der Tags mit einer Reihe von Schlüsselwörtern übereinstimmen. Die Tags sind alle nur normale Textwörter, die von einem "<>" umgeben sind, und ein End-Tag, umgeben von "" für jedes erzeugte Tag.Separieren von benutzerdefinierten Tags Inhalt mit Regex in Java

Ex. von lesen text

<name>stuff<name/> 
    <locations>example of text<locations/> 
    <storybattles>more text somehow<storybattles/> 
    <maincharacter>characters n stuff <maincharacter/> 
//continues on with random tag text values 

RÜCKKEHR,

"stuff" 
"example of text" 
"more text somehow" 
"characters n stuff" 

bevorzugt Verwendung Case-

String inputText="pretend there are tags in here"; 
//Please pretend I added several keywordsd to the keywords list 
ArrayList<String> keywords=new ArrayList<String>(); 
String[] allTheAnswers=kindStackOverflowMentorMethod(inputText,keywords); 

Während ich dies von mir mit meiner begrenzten Kenntnis der Regex tun, ich bin nur kriechend Wie ich weiß, kann dies viel besser gemacht werden. Wenn du eine Erklärung für jeden Teil des Regex-Ausdrucks, den du benutzt, eingibst (oder eine andere Lösung, die ein brillanter Verstand aufbaut), bekommst du zusätzliche Punkte von mir.

+0

Ich habe meine eigenen Methoden versuchen, aber es wurde im Wesentlichen mich Hacking und Hieb durch den Prozess mit .split, .remove usw. ich nur einen winzigen Schnipsel benötigt der verständlichen Regex, um meine Füße auf den Boden zu bekommen ... oder davon weg. – Edge363

Antwort

0

Hier ist ein funktionierendes Beispiel dafür, wie ich es tun würde:

private static final String DATA = "<name>stuff<name/>\n" + 
     " <locations>example of text<locations/>\n" + 
     " <storybattles>more text somehow<storybattles/>\n" + 
     " <maincharacter>characters n stuff <maincharacter/>"; 

private static final List<String> KEYWORDS = Arrays.asList(
     new String[]{"name", "locations"}); 

private static final String PATTERN = "<%1$s>(.+?)<%1$s/>"; 

public static void main(String[] args) { 

    List<String> strs = new ArrayList<>(); 
    for (String keyword : KEYWORDS) { 
     String tempPattern = String.format(PATTERN, keyword); 
     Pattern pattern = Pattern.compile(tempPattern); 
     Matcher matcher = pattern.matcher(DATA); 

     while(matcher.find()){ 
      strs.add(matcher.group(1)); 
     } 
    } 
} 

Regex101 Fiddle

+0

Vielen Dank! Es funktioniert genau wie beabsichtigt, können Sie mir jetzt sagen, wie "% 1 $" und "s" zwischen den "<" and ">" funktionieren? – Edge363

+0

Dieser Wert ist ein Platzhalter für 'String.format()', er ist nicht Teil der Regex. Bevor ich das Pattern-Objekt erstelle, ändere ich diesen Wert in eine literale Zeichenfolge wie "name", so dass die Regex zu " (. +?) " wird. Jede Iteration über die Schlüsselwortliste ändert die Regex in das aktuelle Schlüsselwort zwischen '<>'. – dambros

0

Sind Sie für diese suchen?

import java.util.ArrayList; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 


public static void main(String[] args) { 

    String inputText=" <name>stuff<name/>\n"+ 
     " <locations>example of text<locations/>\n"+ 
     " <storybattles>more text somehow<storybattles/>\n"+ 
     " <maincharacter>characters n stuff <maincharacter/>"; 

    //Please pretend I added several keywordsd to the keywords list 
    ArrayList<String> keywords=new ArrayList<>(); 
    keywords.add("locations"); 
    keywords.add("maincharacter"); 

    //Call the function 
    ArrayList<String> allTheAnswers=kindStackOverflowMentorMethod(inputText,keywords); 

} 

public static ArrayList<String> kindStackOverflowMentorMethod(String inputText, ArrayList<String> keywords){ 
    ArrayList<String> values=new ArrayList<>(); 
    Matcher m = Pattern.compile("<([a-z][a-z0-9]*)>(.*?)<(?:\\1)\\/>").matcher(inputText); 
    while (m.find()){ 
     if (keywords.indexOf(m.group(1)) > -1) { 
      values.add(m.group(2));    
     } 
    } 
    return values; 
} 

REGEX ERKLÄRUNG

<     # match < literally 
([a-z][a-z0-9]*) # first capturing group - match TAG name 
         should start with a letter, followed by 
         0 or more letters or numbers 
>     # match > literally 
(.*?)    # 2nd capturing group - match content surrounded by TAGs 
         non-greedy match 
<     # match < literally 
(?:\1)    # non-capturing group - match previous matched TAG name 
\/>     # match /> literally 
+0

Absolut! Vielen Dank für die Erklärung. Also "?: \ 1" bedeutet, dass Sie eine vorher übereinstimmende Reihe von Charakteren greifen? Weil das und das Ändern des Namens, der durchsucht werden sollte, mich daran hinderte, vorwärts zu gehen. Auch wenn ich eine andere Frage stellen kann, überprüft die Schleife im Wesentlichen, ob das Schlüsselwort innerhalb des Textes ist, oder findet sie den Ort und verwendet sie, um bestimmte Werte zu lokalisieren? – Edge363

+0

Nicht-einfangende Gruppe wird von '(?: Pattern)' gespendet, und '\ 1' bedeutet zuvor übereinstimmende Zeichenfolgen. 'if (keywords.indexOf (m.gruppe (1))> -1)' prüft, ob das Schlüsselwort in der aktuellen übereinstimmenden Gruppe 1 ist; Wenn dies der Fall ist, fügen Sie der Liste den entsprechenden Wert hinzu. Dies ist ein Eins-zu-eins-Paar, sodass Sie den Standort nicht finden müssen. :) – Quinn