我正在解析一个大型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”的那些。
.+?(item1).+?(item2)
是语法吗? (类似于C#)源样本:
<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 = "UI Framework" </ac:parameter>
<ac:parameter ac:name="maximumIssues">20</ac:parameter>
</ac:structured-macro>
最佳答案
如评论中所述-不要对XML使用正则表达式!
而是使用.NET的内置功能来解析它并使用它:
$XmlDoc = [xml](Get-Content .\largefile.xml)
现在,$ XmlDoc变量包含一个实时的
XmlDocument
,我们可以通过编程方式检查和修改(使用XPath
),而不仅仅是纯文本从您的简短摘录的内容中,我猜想这个大的xml文件是一个XSLT模板,其中包含用于Confluence的JIRA宏。
由于Confluence使用 namespace 前缀
ac
-我们需要创建一个 namespace 管理器以便使用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")
关于regex - 匹配语法问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32675746/