匹配语法问题

时间:2015-09-20 04:16:05

标签: regex xml powershell

我正在解析查找特定内容的大型XML文件,例如

$matches = [regex]::matches($content, '(<ac:structured-macro.+?ac:name="jira".+?</ac:structured-macro>)'

即。返回以<ac:structured-macro>开头和结尾的部分,其中包含“jira”。

我发现的还有其他记录,例如

<ac:structured-macro blah blah </ac:structured-macro>
<ac:structured-macro blah ac:name="jira" blah </ac:structured-macro>

我希望它只能找到带有“jira”的那些。

  1. 如果您发现“ac:structured-macro”结尾并且没有找到“jira”部分重新开始搜索,我怎么告诉它?

  2. 一旦我找到了这个,我需要在这场比赛中获得部分。语法是.+?(item1).+?(item2)吗? (类似于C#)

  3. 来源样本:

    <ac:structured-macro ac:name="jira">
        <ac:parameter ac:name="columns">key,summary,type,created,updated,due,assignee,reporter,priority,status,resolution</ac:parameter>
        <ac:parameter ac:name="server">JIRA (site.atlassian.net)</ac:parameter>
        <ac:parameter ac:name="serverId">72f475d9-a9b2</ac:parameter>
        <ac:parameter ac:name="jqlQuery">project = PLATFORM AND issuetype in (Bug, Question, Story) AND fixVersion = 1.12.1 AND component = &quot;UI Framework&quot;   </ac:parameter>
        <ac:parameter ac:name="maximumIssues">20</ac:parameter>
    </ac:structured-macro>
    

1 个答案:

答案 0 :(得分:4)

正如评论中所提到的 - 不要使用正则表达式来实现XML!

相反,使用.NET的内置功能来解析它并使用它:

$XmlDoc = [xml](Get-Content .\largefile.xml) 

现在,$ XmlDoc变量包含一个实时XmlDocument,我们可以通过编程方式检查和修改(使用XPath),而不仅仅是纯文本

从你的简短片段的内容来看,我猜这个大的xml文件是一个包含Confluence的JIRA宏的XSLT模板。

由于Confluence使用名称空间前缀ac - 我们需要创建一个名称空间管理器,以便使用XPath查询文档:

$XmlNSMgr = New-Object System.Xml.XmlNamespaceManager $XsltDoc.NameTable
$XmlNSMgr.AddNamespace("xsl","http://www.w3.org/1999/XSL/Transform")
$XmlNSMgr.AddNamespace("ac","http://www.atlassian.com/schema/confluence/4/ac/")

现在,您可以使用SelectNodes()方法和XPath表达式选择所需的节点:

$XPathExpression = '//ac:structured-macro'
$MacroNodes = $XmlDoc.SelectNodes($XPathExpression, $XmlNSMgr)

$MacroNodes现在是文档中找到的所有<ac:structured-macro>个节点的集合。

要仅选择存在ac:name="jira"属性的节点,请在XPath表达式中添加一个子句:

$XPathExpression = '//ac:structured-macro[@ac:name = "jira"]'
$JiraMacroNodes = $XmlDoc.SelectNodes($XPathExpression, $XmlNSMgr)

您甚至可以编辑节点,并在保存编辑时修改文档:

$JiraMacroNodes |ForEach-Object {
    $_.SetAttribute("attrName","newValue")
}
$XmlDoc.Save("C:\path\to\new.xslt")