我在SoapMessage看起来像这样:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Action xmlns="http://www.w3.org/2005/08/addressing">http://service.xxx.dk/DialogModtag</Action>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:382b4943-26e8-4698-a275-c3149d2d889e</MessageID>
<To xmlns="http://www.w3.org/2005/08/addressing">http://xxx.dk/12345678</To>
<RelatesTo xmlns="http://www.w3.org/2005/08/addressing">uuid:cb2320dc-c8ab-4880-94cb-2ab68129216f</RelatesTo>
</soap:Header>
<soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-2515">
Some content ...
</soap:Body>
我试图提取&lt; Action&gt;的内容&lt; Header&gt;中的标记标记使用这样的代码:
Pattern PATTERN_SOAP_ACTION =
Pattern.compile(".*Header.*Action.*>(.*)<.*Action.*Header.*", Pattern.DOTALL);
String text = readFile("c:\\temp\\DialogUdenBilag.xml");
Matcher matcherSoapAction = PATTERN_SOAP_ACTION.matcher(text);
if (matcherSoapAction.matches()) { System.out.println(matcherSoapAction.group(1)); }
else { System.out.println("SaopAction not found"); }
这似乎对小肥皂消息有效。但是当soap:Body增长到+ 1MB时,则matches()函数调用需要几分钟才能完成。
任何让我的正则表达式模式更加CPU友好的想法?
答案 0 :(得分:2)
您希望使用XML解析器来获得更加CPU友好的解决方案。
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("c:\\temp\\DialogUdenBilag.xml"));
boolean found=false;
boolean inHeader=false;
String actionContent = "";
while(!found && reader.hasNext()){
if(reader.next() == XMLStreamConstants.START_ELEMENT) {
String localName=reader.getLocalName());
if ("Header".equalsIgnoreCase(localName) {
inHeader = true;
}
if(inHeader && "Action".equalsIgnoreCase(localName) {
int evt=reader.next();
do {
if (evt==XMLStreamConstants.CHARACTERS) {
actionContent = reader.getText().trim();
found=true;
break;
}
evt=reader.next();
} while(evt != XMLStreamConstants.END_ELEMENT);
}
}
}
if (found) {
System.out.println(actionContent);
} else {
System.out.println("SaopAction not found");
}
这个小片段有点冗长但你会得到你的答案而不是查看整个 XML代码。实际上,代码段会在找到soap:Action
标记后停止,然后返回此代码的文本内容。
答案 1 :(得分:1)
使用正则表达式来解析XML是邪恶的,may incur the Wrath of the One whose Name cannot be expressed in the Basic Multilingual Plane.如果需要解析XML,请使用实际的XML解析器 - 这就是它的用途。像这样的情况也是XPath表达式的用法:
javax.xml.xpath.XPath xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContextMap(
"s", "http://schemas.xmlsoap.org/soap/envelope/",
"a", "http://www.w3.org/2005/08/addressing"));
javax.xml.xpath.XPathExpression expression = xpath.compile("//s:Header/a:Action");
String result = expression.evaluate(new org.xml.sax.InputSource(new FileReader("c:\\temp\\DialogUdenBilag.xml")));
(请注意,NamespaceContextMap
不是标准类 - 有关实施,请参阅here。)
至于你的正则表达式:它被编写为不必要地匹配整个输入字符串,并进行大量的最大匹配而不是最小匹配。如果你的表达式更紧密地关注文档的相关位(例如,"<((?:\\w+:)?)?Header\\b[^>]*>.*?<((?:\\w+:)?)Action\\b[^>]*>(.*?)</\\2Action>.*?</\\1Header>"
),并且调用Matcher.find()
来进行子串匹配,那么你可以通过少量CPU来咀嚼。也就是说,用regexp解析XML是不好的做法 - 你真的应该使用XML解析器了!