2017-08-24 91 views
0

我試圖解析一個XML文檔(特別是一個Sublime顏色主題),並且我試圖使用負向前視來阻止我不想要的匹配,但它似乎沒有正常工作。在前面和後面匹配的Ruby中的負向前瞻

的模式如下:

/ 
<key>name<\/key> 
.*?      # find as little as possible including new lines 
<string>(.*?)<\/string> # Match the name of this color Rule 
.*? 
<dict> 
((?!<\/dict>).)*?  # After the second opening <dict>, do not allow a closing </dict> 
<key>foreground<\/key> 
.*? 
<string>(.*?)<\/string> # Match the hex code for the name found in Match 1. 
/mx      # Treat a newline as a character matched by . 
         # Ignore Whitespace, comments. 

正被匹配的字符串是:

<dict> 
     <key>name</key> 
     <string>**Variable**</string> 
     <key>scope</key> 
     <string>variable</string> 
     <key>settings</key> 
     <dict> 
      <key>fontStyle</key> 
      <string></string> 
     </dict> 
    </dict> 

    <dict> 
     <key>name</key> 
     <string>Keyword</string> 
     <key>scope</key> 
     <string>keyword - (source.c keyword.operator | source.c++ keyword.operator | source.objc keyword.operator | source.objc++ keyword.operator), keyword.operator.word</string> 
     <key>settings</key> 
     <dict> 
      <key>foreground</key> 
      <string>**#F92672**</string> 

的整個字符串匹配時,與**Variable**作爲第一捕獲組和**#F92672**作爲第二。理想情況下,我希望在第二部分中第一個捕獲組成爲Keyword。我認爲負面預測的存在意味着第一部分不會成爲比賽的一部分,因爲它會看到</dict>而無法匹配。

有誰知道我是否做錯了,我能做些什麼來解決它?謝謝!

回答

1

這裏是一種與引入nokogiri做到這一點:

require 'nokogiri' 

theme = Nokogiri::XML.fragment(xml) 
puts theme.xpath('./dict[1]/key[text()="name"]/following-sibling::string[1]').text 
#=> "**Variable**" 
puts theme.xpath('.//dict[preceding-sibling::key[1][text()="settings"]]/string').text 
#=> "**#F92672**" 

的第一個XPath取第一dict並發現key含有「名稱」,然後採取下列string元素的文本。

第二個XPath在包含「設置」的key之後立即尋找dict,並檢索其string元素的文本。

請注意,如果您解析完整文檔而不是給定片段,則需要進行一些更改,例如將呼叫更改爲theme = Nokogiri::XML.parse(xml),並從XPath表達式中刪除前導.

+0

謝謝!我對xpath不太舒服,並且在Nokogiri遇到麻煩,但我會再試一次。 – mcheah

0

第一個dict與字符串**Variable**和第二個與Keyword具有相同的結構。而且你想通過負面預測來區分它們,但這是不可能的。

變化((?!<\/dict>).)*?(((?!<\/dict>).)*?)調試 ,你可以看到新的基團含量

result=" 
     <key>name</key> 
     <string>Keyword</string> 
     <key>scope</key> 
     <string>keyword - (source.c keyword.operator | source.c++ keyword.operator | source.objc keyword.operator | source.objc++ keyword.operator), keyword.operator.word</string> 
     <key>settings</key> 
     <dict> 
      " 

這滿足你的負面先行。

即使添加更多條件(僅使用結構作爲條件而不是內容),因爲相同的結構,**Variable**將始終在**#F92672**之前。

因此使用xml解析器可能是一個更好的選擇。