正则表达式以匹配来自多个相似标签的标签数据

时间:2018-07-23 11:17:38

标签: java regex

我正在尝试从下面提到的XML(可能有效或无效)中提取cxml,其中包含多个cxml标记。我想要最顶级的cxml及其子cxml标记,但是得到的结果与预期不符。
正则表达式:

public static String selectCxmlFromXml(String xml) {
    String cxml = "";
    Pattern pattern = Pattern.compile(".*(<cXML.*</cXML>).*", Pattern.DOTALL);
    Matcher matcher = pattern.matcher(xml);
    if (matcher.matches()) {
        cxml = matcher.group(1);
    }
    return cxml;
}

输入XML(这不是有效的XML):

<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.037/cXML.dtd">1532298890669-3937185683464996079@216.109.111.68
<cXML payloadID="1532333614215-4720337288049634328@216.109.111.11" timestamp="2018-07-23T01:13:34-07:00">
   <Response>
      <Status code="200" text="OK"/>
      <GetPendingResponse>
         <cXML
            payloadID="1532333614208-7005041222787302474@216.109.111.11" timestamp="2018-07-23T01:13:34-07:00">
            <Message>
               <DataAvailableMessage>
                  <InternalID domain="PendingMessages">140000000000000000010977255</InternalID>
               </DataAvailableMessage>
            </Message>
         </cXML>
      </GetPendingResponse>
   </Response>
</cXML>

预期的响应:

<cXML payloadID="1532333614215-4720337288049634328@216.109.111.11" timestamp="2018-07-23T01:13:34-07:00">
   <Response>
      <Status code="200" text="OK"/>
      <GetPendingResponse>
         <cXML
            payloadID="1532333614208-7005041222787302474@216.109.111.11" timestamp="2018-07-23T01:13:34-07:00">
            <Message>
               <DataAvailableMessage>
                  <InternalID domain="PendingMessages">140000000000000000010977255</InternalID>
               </DataAvailableMessage>
            </Message>
         </cXML>
      </GetPendingResponse>
   </Response>
</cXML>

响应得到(不正确):

<cXML payloadID="1532333614208-7005041222787302474@216.109.111.11" timestamp="2018-07-23T01:13:34-07:00">
            <Message>
               <DataAvailableMessage>
                  <InternalID domain="PendingMessages">140000000000000000010977255</InternalID>
               </DataAvailableMessage>
            </Message>
         </cXML>
      </GetPendingResponse>
   </Response>
</cXML>

请注意,第一个cxml声明及其数据已被跳过。
如果我使用.*(<cXML.*?</cXML>).*,则仅选择内部cxml,而跳过外部cxml。

<cXML payloadID="1532333614208-7005041222787302474@216.109.111.11" timestamp="2018-07-23T01:13:34-07:00">
   <Message>
        <DataAvailableMessage>
           <InternalID domain="PendingMessages">140000000000000000010977255</InternalID>
        </DataAvailableMessage>
     </Message>
</cXML>  

我在这里做错了什么?

4 个答案:

答案 0 :(得分:0)

经过一些摆弄,我遇到了这个正则表达式:

Traceback (most recent call last):
  File "SDK_communicator.py", line 3, in <module>
    sdkDll = WinDLL("C:\jhgsdk.dll")
  File "c:\python36\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found


from ctypes import *
sdkDll = WinDLL("C:\sdk.dll")

I also tried:
  C:\\sdk.dll
  C:\sdk.dll
  C:/sdk.dll

解释其实际作用:

  1. (<cXML>|<cXML.+>(?:\s|.)*<\/cXML>) 与开始标签匹配。可以包含或不包含属性。
  2. <cXML>|<cXML.+>是一个 not-captureing-group ,它允许空白((?:\s|.)*)和其他字母(\s)的每种组合都匹配。 / li>
  3. .与结束标记匹配。

Working demo

答案 1 :(得分:0)

如果您原本已接受-遵循,遵守,遵守-标准,协议,RFC等,则没有人应该发送无效的XML。 请注意,可以在CDATA部分中发送非结构化数据。

但是,如果说有充分的理由要处理无效的XML,那么无效将是什么呢?以可预测的方式无效吗?让我们知道因为使用懒惰/贪婪的正则表达式可以(或者不可以)取决于内容的长度和正则表达式处理器。

如果您对顶级cXML感兴趣,请回答您的问题。我会简单地将字符串从从 String 开始的<cXML的第一次出现到从字符串的末尾(向后)的</cXML>的第一次出现的子字符串。您是否希望使用自闭合标签/>

答案 2 :(得分:0)

我发现我做错了。两件事:
1.使用find()代替match()
2.将正则表达式更改为(<cXML.*</cXML>),它将捕获整个cXML

新方法将是:

public static String selectCxmlFromXml(String xml) {
    String cxml = "";
    Pattern pattern = Pattern.compile("(<cXML.*</cXML>)", Pattern.DOTALL);
    Matcher matcher = pattern.matcher(xml);
    if (matcher.find()) {
        cxml = matcher.group(1);
    }
    return cxml;
}

答案 3 :(得分:0)

这个问题已经有了很好的答案,但是我想分享这个网站:

http://www.regexplanet.com/advanced/java/index.html

在用Java编写正则表达式时确实很有帮助。 每当需要写一些奇怪的正则表达式时,我都会用它。

希望这会有所帮助。