代码之家  ›  专栏  ›  技术社区  ›  Mocky

在Java中用REGEX解析XML

  •  3
  • Mocky  · 技术社区  · 17 年前

    <?xml version="1.0"?>
    <StandardDataObject xmlns="myns">
      <DataElements>
        <EmpStatus>2.0</EmpStatus>
        <Expenditure>95465.00</Expenditure>
        <StaffType>11.A</StaffType>
        <Industry>13</Industry>
      </DataElements>
      <InteractionElements>
        <TargetCenter>92f4-MPA</TargetCenter>
        <Trace>7.19879</Trace>
      </InteractionElements>
    </StandardDataObject>
    

    我需要的输出是: [{EmpStatus:2.0},{支出:95465.00},{员工类型:11.A},{行业:13}]

    "<([A-Za-z0-9]+?)>([A-Za-z0-9.]*?)</"
    

    这是我构造的正则表达式,它有一个问题,它在结果中错误地包含了{Trace:719879}。依赖XML中的新行或任何其他明显的格式不是一个选项。

    private static final Pattern PATTERN_1 = Pattern.compile(..REGEX..);
    private List<DataElement> listDataElements(CharSequence cs) {
        List<DataElement> list = new ArrayList<DataElement>();
        Matcher matcher = PATTERN_1.matcher(cs);
        while (matcher.find()) {
            list.add(new DataElement(matcher.group(1), matcher.group(2)));
        }
        return list;
    }
    

    如何将正则表达式更改为只包含数据元素而忽略其余元素?

    8 回复  |  直到 17 年前
        1
  •  52
  •   Dour High Arch    17 年前

    XML不是一种常规语言。你 不能

        2
  •  15
  •   Jan Goyvaerts    17 年前

    如果您可以假设DataElements标记之间的所有内容都具有表单值,那么这在Java中应该是可行的。即没有属性,也没有嵌套元素。

    Pattern regex = Pattern.compile("<DataElements>(.*?)</DataElements>", Pattern.DOTALL);
    Matcher matcher = regex.matcher(subjectString);
    Pattern regex2 = Pattern.compile("<([^<>]+)>([^<>]+)</\\1>");
    if (matcher.find()) {
        String DataElements = matcher.group(1);
        Matcher matcher2 = regex2.matcher(DataElements);
        while (matcher2.find()) {
            list.add(new DataElement(matcher2.group(1), matcher2.group(2)));
        } 
    }
    
        3
  •  4
  •   activout.se    17 年前

    改用XPath!

        4
  •  2
  •   Greg    17 年前

    如果必须使用RE,为什么不分两个阶段进行? DataElements>.*?</DataElements

        5
  •  1
  •   Alnitak    17 年前

    有没有任何理由不使用合适的XML解析器而不是正则表达式?这对于正确的库来说是微不足道的。

        6
  •  1
  •   Guðmundur Bjarni    17 年前

    Commons-Digester , JAXP (与Java 5+捆绑销售)或 JAXB

        7
  •  1
  •   James Van Huis    17 年前

    然而,如果你真的那么固执,你应该能够调整你的代码,把标签排除在DataElements标签之外。

    private static final Pattern PATTERN_1 = Pattern.compile(..REGEX..);
    private static final String START_TAG = "<DataElements>";
    private static final String END_TAG = "</DataElements>";
    private List<DataElement> listDataElements(String input) {
        String cs = input.substring(input.indexOf(START_TAG) + START_TAG.length(), input.indexOf(END_TAG);
        List<DataElement> list = new ArrayList<DataElement>();
        Matcher matcher = PATTERN_1.matcher(cs);
        while (matcher.find()) {
            list.add(new DataElement(matcher.group(1), matcher.group(2)));
        }
        return list;
    }
    

    如果dataelements标记不存在,那么这将非常失败。

        8
  •  0
  •   Amith Perera    8 年前

    尝试通过属性文件解析Reg Ex,然后创建模式对象。我解决了通过XMLBeans注入Reg-Ex时遇到的相同问题。

    我需要通过在Spring中注入来解析regex'(.)(D[0-9]{7}.D[0-9]{9}.D[A-Z]{3}[0-9]{4})()'。但它不起作用。一旦尝试在Java类中使用相同的Reg Ex硬编码,它就成功了。

    Next I tried to load that Reg Ex via property file while injecting it. It worked fine.
    
      p:remoteDirectory="${rawDailyReport.remote.download.dir}"
      p:localDirectory="${rawDailyReport.local.valid.dir}"
      p:redEx="${rawDailyReport.download.regex}"
    

    在属性文件中,属性定义如下。

    rawDailyReport.download.regex=(。 )(D[0-9]{7}\.D[0-9]{9}\.D[A-Z]{2}[0-9]{4})()。

    这是因为带有占位符的值是通过org.springframework.beans.factory.config.propertyplaceholderconfigure加载的,它在内部处理这些xml敏感字符。

    谢谢 埃米思