【问题标题】:Is possible to get elements from XML using Notepad++ Regex? [duplicate]是否可以使用 Notepad++ Regex 从 XML 中获取元素? [复制]
【发布时间】:2019-03-20 15:04:24
【问题描述】:

我有一个具有不同 Item 的 XML,其中可能包含名为 SerialNumber 的属性 Setting。我正在尝试获取所有项目名称后跟序列号。

我的方法是使用 Notepad++ 正则表达式来获取 Item 的名称和名为 SerialNumber 的属性 Setting 的值,如下所示:

发件人0;3990 发件人3;4444 发件人4;7774

但尝试它我唯一能得到的是notepad++选择所有文本......我的快速方法是这样的:

^<Item Name="(.*)" Category=".*<Setting Name="SerialNumber">(.*)</Setting>.*</Item>

并替换:

(\1);(\2)

XML:

    <Item Name="Sender0" Category="" ClassName="Cars" Schedule="" Enabled="true">
     <Setting>...</Setting>
     <Setting Name="SerialNumber">3990</Setting>
     <Setting>...</Setting>
    </Item>
    <Item Name="Sender1" Category="" ClassName="Cars" Schedule="" Enabled="true">
     <Setting>...</Setting>
     <Setting>...</Setting>
     <Setting>...</Setting>
    </Item>
    <Item Name="Sender2" Category="" ClassName="Cars" Schedule="" Enabled="true">
     <Setting>...</Setting>
     <Setting>...</Setting>
     <Setting>...</Setting>
    </Item>
    <Item Name="Sender3" Category="" ClassName="Cars" Schedule="" Enabled="true">
     <Setting>...</Setting>
     <Setting Name="SerialNumber">4444</Setting>
     <Setting>...</Setting>
    </Item>
    <Item Name="Sender4" Category="" ClassName="Cars" Schedule="" Enabled="true">
     <Setting>...</Setting>
     <Setting Name="SerialNumber">7774</Setting>
     <Setting>...</Setting>
    </Item>

希望你能帮助我,谢谢:)

【问题讨论】:

  • Regex + XML = evil evil evil ...不是我的反对意见,但 NPP 中的正则表达式在这里也不是最好的。研究使用 XML 解析器。
  • 蒂姆是对的。您还可以使用哪些其他技术?例如,Powershell 是一种选择吗?
  • Regex 不起作用,因为 regex 不能与 XML 一起使用。使用一种用于 XML 处理的工具,它们的存在是有原因的。
  • 确实,是的。如果处理此文件是您的任务,我建议使用 Powershell,因为该方法在 Windows 中具有零外部依赖性。如果您只是选择它作为学习正则表达式的一种方式,我建议您使用 XML 以外的东西。

标签: regex xml notepad++


【解决方案1】:

我认为正则表达式是viable。除非你遗漏了问题的一些细节。

试试这个:

搜索:\s*&lt;Item\s*Name="([^"]+)"[^&gt;]+&gt;(?:\s*&lt;Setting&gt;.*?&lt;\/Setting&gt;)*(?:\s*&lt;Setting Name="SerialNumber"&gt;(.*?)&lt;\/Setting&gt;)?(?:\s*&lt;Setting&gt;.*?&lt;\/Setting&gt;)*\s*&lt;\/Item&gt;

替换为:(?2\1;\2 )

在 notepadd++ 中,给定输入的输出将是:Sender0;3990 Sender3;4444 Sender4;7774

注意:不要不要使用. matches new line 选项。另外,如果需要,请使用match case

说明:

\s*                  # 0 or more spaces (space, tab, new line...)
<Item                # Literal '<item'
    \s*              
    Name="           # Literal 'Name="'
        ([^"]+)      # Any non (") character repeated one or more times
                     #   stored on the first capturing group
    "                # Literal "
    [^>]+            # Any non (>) character repeated one or more
>                    # Literal >
# After searching for Item Name, there must exists its serial number.
# The serialNumber may be sorrounded by other settings, so We will search:
# perhapsSomeSettings + serialNumber + perhapsSomeSettings
# so that we will be able to find (if exists) the serial number wether it
# is placed as the first, last or middle tag.
(?:     # group
    \s*
    <Setting>.*?<\/Setting>
)*      # repeat 0 or more
(?:     # This 'setting' group will have the serial number
    \s*
    <Setting Name="SerialNumber">
    (.*?)    # We capture the data (second capturing group)
    <\/Setting>
)?     # Optional
(?:    
    \s*
    <Setting>
        .*?
    <\/Setting>
)*
\s*
<\/Item>

请参阅 this 关于贪婪/懒惰的量词。

对于替换我们使用(?2\1;\2 )

(?2) 是 notepadd++ (boost) 正则表达式中的特殊语法。这意味着如果第二个捕获组存在,则应用里面的内容。所以在我们的例子中(?2\1;\2 ) 如果存在第二个捕获组,我们的替换将是第一个捕获组(名称)、; 和第二个捕获组(序列号)

【讨论】:

  • 如果您能稍微解释一下您的正则表达式,我将非常感激,出于学习目的并防止像我这样的人陷入此类问题:)
  • 当然,@Ralsho。我编辑了我的答案以添加解释。
猜你喜欢
  • 2017-01-27
  • 2020-06-02
  • 2023-01-26
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 2021-12-06
  • 2018-08-30
相关资源
最近更新 更多