【问题标题】:Regular expression to match only direct subtag?正则表达式只匹配直接子标签?
【发布时间】:2013-02-14 15:04:48
【问题描述】:

我正在编写一个简单的 RSS 解析器(我知道已经编写了很多),但我偶然发现了一个问题。假设我有以下 RSS 提要:

<channel>
  <title>Sunset Boulevard</title>
  <link>http://www.imdb.com/title/tt0043014/</link>
  <description>A hack screenwriter writes a screenplay..</description>
  <language>English</language>
  <item>
    <rating>8.6</rating>
  </item>
</channel>

我有一种方法可以通过给定的标签和子标签将它们提取到一个简单的哈希中。这是我的“方法”:

def extract_text_from_tag(text, tag)
  text =~ /<#{tag}.*?>(?<tag_text>.*?)<\/#{tag}>/m ? $~[:tag_text] : ''
end

为了解析频道,我首先提取其文本,然后使用一组预定义的标签(标题、链接等)提取它们的数据。但是,我希望我的正则表达式只匹配我的标签的直接子代。

例如,如果我传递“标题”、“链接”、“描述”、“语言”和“评级”标签,我想匹配除“评级”之外的所有标签(因为它是项目的子项)。

【问题讨论】:

  • 这就是为什么用正则表达式解析 XML 很棘手的原因。可能(对于明确定义的情况),但很棘手。
  • 是否需要使用 regex-es 执行此操作?用 xpath 或通过 dom 解析解决这个问题似乎更容易......
  • MichaelMyers - 我知道这很棘手,但格式定义明确。 Equinoxel - 是的,这是一项要求。
  • 顺便问一下,这是 Ruby 吗?
  • 我强烈推荐阅读“RegEx match open tags except XHTML self-contained tags”。它涵盖了尝试使用正则表达式解析 HTML 或 XML 的问题。虽然编写 RSS 解析器看起来“有趣”,但您确实应该考虑重用轮子,而不是自己发明。 RSS 在野外是一团糟,有几个规范,不包括 ATOM,它也用于提要。我编写了一个解析所有变体、处理数百个提要的程序,这是一个“有趣”的挑战。

标签: ruby regex rss pcre


【解决方案1】:

我从 cmets 看到,您必须使用正则表达式而不是正确的 XML 解析器来解析这个 RSS 提要。

但是,作为反例,以下是使用 Nokogiri 的解决方案:

doc = Nokogiri::XML(rss_xml_string)
doc.xpath('/channel/*').each do |node| # For each child of the root "channel".
  next if node.children.length > 1 # Skip nodes with multiple children.
  puts node.name + ': ' + node.text
end
# title: Sunset Boulevard
# link: http://www.imdb.com/title/tt0043014/
# description: A hack screenwriter writes a screenplay..
# language: English

【讨论】:

    【解决方案2】:

    请注意,事情可能会变得复杂,超出了您可以使用正则表达式的能力,这里有一些建议:

    您可以使用[^&lt;&gt;]*? 而不是.*?,假设“”在XML 中被正确转义。

    这将防止在 item 包含子项时提取其内容,这可能是也可能不是所需的行为(我认为这在你的例子,但一般来说可能不太好)。

    如果您仍然需要提取“项目”的内容(如果有的话),除了可能的子项目,您需要使用条件语句,如果我没记错的话,Ruby 不支持。

    您可以将其替换为测试标记是否包含子元素并相应地应用正则表达式的方法,但它确实变得相当复杂。

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 2018-09-22
      • 1970-01-01
      相关资源
      最近更新 更多