在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