Разбейте задачу на две отдельные части:
1) Разоберите данные XML с помощью подходящего анализатора XML, чтобы извлечь нужный текст.
2) Для извлеченные текстовые поля, используйте регулярное выражение для извлечения необходимых подстрок.
В следующем примере используется синтаксический анализатор SAX (кстати, я использую Java 13).
Предположим у нас есть файл, содержащий следующее XML:
<root>
<query name="RSmag">
<source>
<model />
</source>
<selection>
<dataItem aggregate="none" name="Code magasin">
<expression>
[Customer ].[Sales ].[L_MOIS]
</expression>
<expression>
cast_varchar([Customer ].[Sales ].[L_MOIS_ANNEE]) + ' ' + cast_varchar([Customer ].[Sales ].[C_ANNEE])
</expression>
</dataItem>
</selection>
<detailFilters>
<detailFilter>
<filterExpression>
[Customer ].[Sales ].[DT_JOUR] <= getdate()
</filterExpression>
</detailFilter>
</detailFilters>
</query>
<query name="RSmag">
<source>
<model />
</source>
<selection>
<dataItem aggregate="none" name="Code magasin">
<expression>
[Customer statistics].[Stores].[C_MAGASIN]
</expression>
</dataItem>
<dataItem aggregate="none" name="Libellé magasin" sort="ascending">
<expression>
[Customer statistics].[Stores].[L_MAGASIN]
</expression>
</dataItem>
</selection>
<detailFilters>
<detailFilter>
<filterExpression>
[Customer statistics].[Stores].[C_DEPOT] <> '500'
</filterExpression>
</detailFilter>
<detailFilter>
<filterExpression>
[Customer statistics].[Stores].[C_MAGASIN]
not in ('005120';'005130';'005140')
</filterExpression>
</detailFilter>
</detailFilters>
</query>
<query name="CAdept_avec_metier_cumul">
<source>
<model />
</source>
<selection>
<dataItem aggregate="none" name="Cod Metier" rollupAggregate="none">
<expression>
[Customer ].[Articles].[COD_DPTG]
</expression>
</dataItem>
<dataItem name="Nombre de tickets" rollupAggregate="total">
<expression>
count(distinct [Customer ].[Sales ].[ID_TICKET])
</expression>
</dataItem>
<dataItem name="Nombre de tickets non affecté" rollupAggregate="total">
<expression>count(distinct
(case
when [Customer ].[Sales ].[C_AFFECTATION] <> 1
then [Customer ].[Sales ].[ID_TICKET]
else null
end)
)
</expression>
</dataItem>
</selection>
</query>
</root>
Обратите внимание на следующее:
a) Я сделал обоснованное предположение, чтобы создать действительный документ XML на основе вопроса примеры данных.
b) Я избежал символов <
и >
в тексте, используя <
и >
.
Шаг 1 - Анализ данных
Это решение использует SAX для синтаксического анализа - существует множество альтернатив.
Следующее будет читать каждую строку входного файла, отбрасывая любые теги, которые не <expression>
или <filterExpression>
тегов. Этот набор может быть скорректирован по необходимости (watchedElements
).
Код собирает текст внутри каждого из этих тегов и очищает его, удаляя символы новой строки и лишние пробелы.
Это дает мы используем набор из 10 текстовых строк, например:
[Customer ].[Sales ].[L_MOIS]
cast_varchar([Customer ].[Sales ].[L_MOIS_ANNEE]) + ' ' + cast_varchar([Customer ].[Sales ].[C_ANNEE])
[Customer ].[Sales ].[DT_JOUR] <= getdate()
[Customer statistics].[Stores].[C_MAGASIN]
[Customer statistics].[Stores].[L_MAGASIN]
[Customer statistics].[Stores].[C_DEPOT] <> '500'
[Customer statistics].[Stores].[C_MAGASIN] not in ('005120';'005130';'005140')
[Customer ].[Articles].[COD_DPTG]
count(distinct [Customer ].[Sales ].[ID_TICKET])
count(distinct (case when [Customer ].[Sales ].[C_AFFECTATION] <> 1 then [Customer ].[Sales ].[ID_TICKET] else null end) )
Шаг 2 - Применение регулярного выражения
Для каждой из этих строк мы используем регулярное выражение, чтобы найти нужные данные:
\[.*?\](\.\[.*?\])*
При этом выполняется поиск открывающего "[", до следующего "]", и повторяется это для нуля или более последующих строк "[" и "]", разделенных точкой.
Чтобы справиться с нежелательными суб-матчами, мы сохраняем только нулевую группу:
Matcher m = pattern.matcher(text);
while (m.find()) {
System.out.println("*** Matches found : " + m.group(0));
}
Это дает нам следующие 12 результатов:
[Customer ].[Sales ].[L_MOIS]
[Customer ].[Sales ].[L_MOIS_ANNEE]
[Customer ].[Sales ].[C_ANNEE]
[Customer ].[Sales ].[DT_JOUR]
[Customer statistics].[Stores].[C_MAGASIN]
[Customer statistics].[Stores].[L_MAGASIN]
[Customer statistics].[Stores].[C_DEPOT]
[Customer statistics].[Stores].[C_MAGASIN]
[Customer ].[Articles].[COD_DPTG]
[Customer ].[Sales ].[ID_TICKET]
[Customer ].[Sales ].[C_AFFECTATION]
[Customer ].[Sales ].[ID_TICKET]
Полное решение
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.Set;
import java.util.HashSet;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ParseFromFileUsingSax {
// Looks for an opening "[" followed by a closing "]" with an
// optional "." to string items together into one group.
Pattern pattern = Pattern.compile("\\[.*?\\](\\.\\[.*?\\])*");
public void parseUsingSax() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
// the tags we will inspect (all others will be skipped):
Set<String> watchedElements = new HashSet();
watchedElements.add("expression");
watchedElements.add("filterExpression");
DefaultHandler handler = new DefaultHandler() {
private boolean inElement = false;
private StringBuilder stringBuilder;
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
if (watchedElements.contains(name)) {
inElement = true;
stringBuilder = new StringBuilder();
}
}
@Override
public void characters(char[] buffer, int start, int length) throws SAXException {
if (inElement) {
stringBuilder.append(buffer, start, length);
}
}
@Override
public void endElement(String uri, String localName,
String name) throws SAXException {
if (watchedElements.contains(name)) {
inElement = false;
String extractedText = formatString(stringBuilder.toString());
System.out.println();
System.out.println("Extracted XML text : " + extractedText);
printMatches(extractedText);
}
}
};
saxParser.parse("C:/tmp/query_data.xml", handler);
} catch (Exception e) {
System.err.print(e);
}
}
private String formatString(String text) {
text = text.replaceAll("\\r\\n|\\r|\\n", " "); // remove newlines
text = text.replaceAll(" *", " "); // collapse multiple spaces
return text.trim(); // remove leading/trailing whitespace
}
private void printMatches(String text) {
Matcher m = pattern.matcher(text);
while (m.find()) {
System.out.println("*** Matches found : " + m.group(0));
}
}
}