0

我有一些看起来像的 xml:

<records>
  <Customer>
    <Reference>123</Reference>
    <Name>John Smith</Name>    
    <Address1>1, The street</Address1>
    <Address2>Upper Town Street</Address2>
    <Address3>Anytown</Address3>
    <Address4>County</Address4>
    <PostCode>POS TCD</PostCode>
  </Customer>
</records>

但对于其中 Address2 是可选的,所以这也是有效的:

<records>
  <Customer>
    <Reference>123</Reference>
    <Name>John Smith</Name>    
    <Address1>1, The street</Address1>
    <Address3>Anytown</Address3>
    <Address4>County</Address4>
    <PostCode>POS TCD</PostCode>
  </Customer>
</records>

(注意:这是一个缩减的 xml 片段)

当指定 Address2 时,我有以下正确匹配的正则表达式:

<Reference>(?<Reference>.*)</Reference>[\w|\W]*<Name>(?<Name>.*)</Name>[\w|\W]*<Address1>(?<Address1>.*)</Address1>[\w|\W]*<Address2>(?<Address2>.*)</Address2>

它不适用于未指定 Address2 的情况。我得到的最接近的是以下内容:

<Reference>(?<Reference>.*)</Reference>[\w|\W]*<Name>(?<Name>.*)</Name>[\w|\W]*<Address1>(?<Address1>.*)</Address1>[\w|\W]*(<Address2>(?<Address2>.*)</Address2>)?

它匹配并填充两个 xml 片段的参考、名称和地址 1,但在两种情况下都将地址 2 留空,而不是第一个片段的地址 2 的值为上城街。

另外:我知道使用 xml 解析器可能会更容易,但 xml 并不干净,这应该是一个快速简单的解决方案(!)。我也知道我可以将其分解为一组正则表达式来解决,但这现在已成为一个智力挑战。我很想有一个解决方案。

4

2 回答 2

2

不要使用,而是修复损坏的并在最有趣的问题上使用你的思想 =)

不是解析文件的正确工具。2013年解析是已解决的问题,不要试图重新发明轮子。

就像您已经说过的,使用XML 解析器。如果您希望我给您其中一些,请在您的原始帖子中添加您的语言。

我知道解析的最好方法是


请参阅RegEx 匹配打开的标签,XHTML 自包含标签除外

于 2013-03-27T14:39:58.743 回答
1

快速而肮脏的答案:

<Reference>(?<Reference>.*)</Reference>[\w\W]*?<Name>(?<Name>.*)</Name>[\w\W]*?<Address1>(?<Address1>.*)</Address1>[\w\W]*?(<Address2>(?<Address2>.*)</Address2>)?

首先,我删除了|; 它没有伤害任何东西,但它是不必要的。 [\w\W]已经意味着一个单词字符,或者一个不是单词字符的字符。像大多数其他元字符一样,|在字符类中失去了它的特殊含义,只匹配它自己。

但重点是将*改为*?,使其不贪婪。每个[\w\W]*最初都会吞噬整个文本的其余部分,然后回溯,以便它可以匹配下一个需要的部分(例如,<Name>(?<Name>.*)</Name>)。但是这Address2部分不是必需的,所以正则表达式引擎不会费心回溯来接受它。

使量词非贪婪会颠倒优先级:在它吞噬下一个字符之前,它首先尝试匹配正则表达式的一部分。这确保了该Address2行在存在时得到匹配,即使它是可选的。

但是,如果您的 XML 确实按照您显示的方式进行了格式化,那么元素之间的所有内容都是空格。我只会使用\s*,而不必担心它匹配太多或太少。

于 2013-03-27T17:12:15.110 回答