在Java中使用REGEXparsingXML

鉴于下面的XML片段,我需要获取DataElements下每个子项的名称/值对列表。 XPath或XMLparsing器不能用于我无法控制的原因,所以我正在使用正则expression式。

<?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},{Expenditure:95465.00},{StaffType:11.A},{Industry:13}]

DataElements下的标签名称是dynamic的,因此不能在正则expression式中直接表示。 标记名称TargetCenter和Trace是静态的,可以在正则expression式中,但是如果有一种方法可以避免硬编码,那将是更可取的。

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

这是我构造的正则expression式,它有错误地将{Trace:719879}包含在结果中的问题。 依赖于XML中的新行或其他明显的格式不是一种select。

下面是我正在使用的Java代码的近似值:

 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; } 

我怎样才能改变我的正则expression式只包含数据元素,而忽略其余的?

这应该在Java中工作,如果您可以假设在DataElements标签之间,所有东西都具有表单的值。 即没有属性,也没有嵌套的元素。

 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))); } } 

XML不是一种常规的语言。 你不能用正则expression式来parsing它。 当你得到嵌套的标签时,你认为可以工作的expression式将会中断,然后当你修复它时,会破坏XML注释,然后是CDATA部分,然后是处理器指令,然后是命名空间……不能工作,使用XMLparsing器。

改用XPath!

你真的应该使用这个XML库。

如果你不得不使用RE,为什么不分两步呢? DataElements>.*?</DataElements那么你现在拥有什么。

有什么原因,你不使用正确的XMLparsing器,而不是正则expression式的? 这对于正确的库来说是微不足道的。

对不起,给你另一个“不要使用正则expression式”的答案,但认真。 请使用Commons-Digester , JAXP (与Java 5+捆绑)或JAXB (与Java 6+捆绑),因为这样可以使您免于受到伤害。

你应该听取每个人的意见。 轻量级的parsing器是一个坏主意。

但是,如果你真的很努力的话,你应该能够调整你的代码,以排除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标记不存在,这将会失败。

再一次,这是一个坏主意,你可能会在未来的某个时间以bug报告的forms重新访问这段代码。

尝试通过属性文件parsingReg Ex,然后创build模式对象。 我解决了我通过xml bean注入Reg Ex时遇到的问题。

例如: – 我需要parsingReg Ex(。)(D [0-9] {7} .D [0-9] {9} .D [AZ] {3} [0-9] {4} )(。)'在春季注入。 但它没有工作。 一旦试图使用相同的Reg Ex硬编码在它的工作的Java类。

Pattern pattern = Pattern.compile(“(。)(D [0-9] {7} .D [0-9] {9} .D [AZ] {2} [0-9] {4})(。 )“); Matcher matcher = pattern.matcher(file.getName()。trim());

 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 [AZ] {2} [0-9] {4})

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

谢谢,Amith