从嵌套XML中解析属性和值

时间:2017-09-06 15:30:04

标签: groovy xml-parsing jira

背景:尝试从XML获取所有属性和值。我尝试过使用XmlParser和XmlSlurper。我对任何其他建议持开放态度(这是XML中的JIRA工作流程,试图将值放入报告中)。

在其上运行attributes()不会返回顶层的任何内容。因此,将其运行到每个()中将使其可用。前三个返回值正常工作,但下一个级别'除非在每个后续阵列上运行每个,否则不会。我真的不知道该怎么做。每个工作流程的长度都不同。我考虑过某种类型的正则表达式,但这看起来似乎不适用于不同长度和各种工作流程。这是一个非常基本的工作流程。其他的则复杂得多,步骤和属性的数量也各不相同 运行children方法返回值,但它是一个列表,而不是在节点类中。我把它放在这里,以显示它将返回什么值。有什么建议吗?

def xml =
    //'<?xml version="1.0" encoding="UTF-8"?>\n' +
    //'<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.8//EN" "http://www.opensymphony.com/osworkflow/workflow_2_8.dtd">\n' +
    '<workflow>\n' +
            '  <meta name="jira.description"></meta>\n' +
            '  <meta name="jira.update.author.key">admin</meta>\n' +
            '  <meta name="jira.updated.date">1503954892468</meta>\n' +
            '  <initial-actions>\n' +
            '    <action id="1" name="Create">\n' +
            '      <meta name="jira.i18n.submit">common.forms.create</meta>\n' +
            '      <meta name="jira.i18n.title">common.forms.create</meta>\n' +
            '      <validators>\n' +
            '        <validator name="" type="class">\n' +
            '          <arg name="permission">Create Issue</arg>\n' +
            '          <arg name="class.name">com.atlassian.jira.workflow.validator.PermissionValidator</arg>\n' +
            '        </validator>\n' +
            '      </validators>\n' +
            '      <results>\n' +
            '        <unconditional-result old-status="null" status="open" step="1">\n' +
            '          <post-functions>\n' +
            '            <function type="class">\n' +
            '              <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueCreateFunction</arg>\n' +
            '            </function>\n' +
            '            <function type="class">\n' +
            '              <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '            </function>\n' +
            '            <function type="class">\n' +
            '              <arg name="eventTypeId">1</arg>\n' +
            '              <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '            </function>\n' +
            '          </post-functions>\n' +
            '        </unconditional-result>\n' +
            '      </results>\n' +
            '    </action>\n' +
            '  </initial-actions>\n' +
            '  <steps>\n' +
            '    <step id="1" name="To Do">\n' +
            '      <meta name="jira.status.id">10000</meta>\n' +
            '      <actions>\n' +
            '        <action id="11" name="Start Progress">\n' +
            '          <meta name="jira.i18n.submit">startprogress.title</meta>\n' +
            '          <meta name="jira.description"></meta>\n' +
            '          <meta name="jira.i18n.title">startprogress.title</meta>\n' +
            '          <results>\n' +
            '            <unconditional-result old-status="Not Done" status="Done" step="2">\n' +
            '              <post-functions>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowupdateissuestatus-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowassigntocurrentuser-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.AssignToCurrentUserFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowcreatecomment-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowgeneratechangehistory-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowreindexissue-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="eventTypeId">13</arg>\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowfireevent-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '                </function>\n' +
            '              </post-functions>\n' +
            '            </unconditional-result>\n' +
            '          </results>\n' +
            '        </action>\n' +
            '        <action id="21" name="Done">\n' +
            '          <meta name="jira.i18n.submit">jira.issuetracking.simple.workflow.action.done.name</meta>\n' +
            '          <meta name="jira.description"></meta>\n' +
            '          <meta name="jira.i18n.title">jira.issuetracking.simple.workflow.action.done.name</meta>\n' +
            '          <restrict-to>\n' +
            '            <conditions>\n' +
            '              <condition type="class">\n' +
            '                <arg name="permission">RESOLVE_ISSUES</arg>\n' +
            '                <arg name="class.name">com.atlassian.jira.workflow.condition.PermissionCondition</arg>\n' +
            '              </condition>\n' +
            '            </conditions>\n' +
            '          </restrict-to>\n' +
            '          <results>\n' +
            '            <unconditional-result old-status="Not Done" status="Done" step="3">\n' +
            '              <post-functions>\n' +
            '                <function type="class">\n' +
            '                  <arg name="field.name">resolution</arg>\n' +
            '                  <arg name="field.value">10000</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueFieldFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowupdateissuestatus-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowcreatecomment-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowgeneratechangehistory-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowreindexissue-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="eventTypeId">13</arg>\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowfireevent-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '                </function>\n' +
            '              </post-functions>\n' +
            '            </unconditional-result>\n' +
            '          </results>\n' +
            '        </action>\n' +
            '      </actions>\n' +
            '    </step>\n' +
            '    <step id="2" name="In Progress">\n' +
            '      <meta name="jira.status.id">3</meta>\n' +
            '      <actions>\n' +
            '        <action id="31" name="Stop Progress">\n' +
            '          <meta name="jira.i18n.submit">stopprogress.title</meta>\n' +
            '          <meta name="jira.description"></meta>\n' +
            '          <meta name="jira.i18n.title">stopprogress.title</meta>\n' +
            '          <results>\n' +
            '            <unconditional-result old-status="Not Done" status="Done" step="1">\n' +
            '              <post-functions>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowupdateissuestatus-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowcreatecomment-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowgeneratechangehistory-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowreindexissue-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="eventTypeId">13</arg>\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowfireevent-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '                </function>\n' +
            '              </post-functions>\n' +
            '            </unconditional-result>\n' +
            '          </results>\n' +
            '        </action>\n' +
            '        <action id="41" name="Done">\n' +
            '          <meta name="jira.i18n.submit">jira.issuetracking.simple.workflow.action.done.name</meta>\n' +
            '          <meta name="jira.description"></meta>\n' +
            '          <meta name="jira.i18n.title">jira.issuetracking.simple.workflow.action.done.name</meta>\n' +
            '          <restrict-to>\n' +
            '            <conditions>\n' +
            '              <condition type="class">\n' +
            '                <arg name="permission">RESOLVE_ISSUES</arg>\n' +
            '                <arg name="class.name">com.atlassian.jira.workflow.condition.PermissionCondition</arg>\n' +
            '              </condition>\n' +
            '            </conditions>\n' +
            '          </restrict-to>\n' +
            '          <results>\n' +
            '            <unconditional-result old-status="Not Done" status="Done" step="3">\n' +
            '              <post-functions>\n' +
            '                <function type="class">\n' +
            '                  <arg name="field.name">resolution</arg>\n' +
            '                  <arg name="field.value">10000</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueFieldFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowupdateissuestatus-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowcreatecomment-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowgeneratechangehistory-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowreindexissue-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="eventTypeId">13</arg>\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowfireevent-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '                </function>\n' +
            '              </post-functions>\n' +
            '            </unconditional-result>\n' +
            '          </results>\n' +
            '        </action>\n' +
            '      </actions>\n' +
            '    </step>\n' +
            '    <step id="3" name="Done">\n' +
            '      <meta name="jira.status.id">10001</meta>\n' +
            '      <actions>\n' +
            '        <action id="51" name="Reopen">\n' +
            '          <meta name="jira.i18n.submit">jira.issuetracking.simple.workflow.action.reopen.name</meta>\n' +
            '          <meta name="jira.description"></meta>\n' +
            '          <meta name="jira.i18n.title">jira.issuetracking.simple.workflow.action.reopen.name</meta>\n' +
            '          <restrict-to>\n' +
            '            <conditions>\n' +
            '              <condition type="class">\n' +
            '                <arg name="permission">RESOLVE_ISSUES</arg>\n' +
            '                <arg name="class.name">com.atlassian.jira.workflow.condition.PermissionCondition</arg>\n' +
            '              </condition>\n' +
            '            </conditions>\n' +
            '          </restrict-to>\n' +
            '          <results>\n' +
            '            <unconditional-result old-status="Not Done" status="Done" step="1">\n' +
            '              <post-functions>\n' +
            '                <function type="class">\n' +
            '                  <arg name="field.name">resolution</arg>\n' +
            '                  <arg name="field.value"></arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueFieldFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowupdateissuestatus-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowcreatecomment-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowgeneratechangehistory-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowreindexissue-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="eventTypeId">13</arg>\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowfireevent-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '                </function>\n' +
            '              </post-functions>\n' +
            '            </unconditional-result>\n' +
            '          </results>\n' +
            '        </action>\n' +
            '        <action id="61" name="Reopen and start progress">\n' +
            '          <meta name="jira.i18n.submit">jira.issuetracking.simple.workflow.action.reopenandstartprogress.name</meta>\n' +
            '          <meta name="jira.description"></meta>\n' +
            '          <meta name="jira.i18n.title">jira.issuetracking.simple.workflow.action.reopenandstartprogress.name</meta>\n' +
            '          <results>\n' +
            '            <unconditional-result old-status="Not Done" status="Done" step="2">\n' +
            '              <post-functions>\n' +
            '                <function type="class">\n' +
            '                  <arg name="field.name">resolution</arg>\n' +
            '                  <arg name="field.value"></arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueFieldFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowupdateissuestatus-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowassigntocurrentuser-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.AssignToCurrentUserFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowcreatecomment-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowgeneratechangehistory-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowreindexissue-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>\n' +
            '                </function>\n' +
            '                <function type="class">\n' +
            '                  <arg name="eventTypeId">13</arg>\n' +
            '                  <arg name="full.module.key">com.atlassian.jira.plugin.system.workflowfireevent-function</arg>\n' +
            '                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>\n' +
            '                </function>\n' +
            '              </post-functions>\n' +
            '            </unconditional-result>\n' +
            '          </results>\n' +
            '        </action>\n' +
            '      </actions>\n' +
            '    </step>\n' +
            '  </steps>\n' +
            '</workflow>\n' +
            ''

def doc = new XmlParser().parseText(xml)
def attr = doc.attributes() //no results

doc.each {

    if (it.attributes()) {
        println( it.name() )
        println( it.attributes() )
        println( it.value() )
        println ""
    }   else  {
       println ( it.children() )

    }

    }

输出:

meta
[name:jira.description]
[]

meta
[name:jira.update.author.key]
[admin]

meta
[name:jira.updated.date]
[1503954892468]

[action[attributes={id=1, name=Create}; value=[meta[attributes={name=jira.i18n.submit}; value=[common.forms.create]], meta[attributes={name=jira.i18n.title}; value=[common.forms.create]], validators[attributes={}; value=[validator[attributes={name=, type=class}; value=[arg[attributes={name=permission}; value=[Create Issue]], arg[attributes={name=class.name}; value=[com.atlassian.jira.workflow.validator.PermissionValidator]]]]]], results[attributes={}; value=[unconditional-result[attributes={old-status=null, status=open, step=1}; value=[post-functions[attributes={}; value=[function[attributes={type=class}; value=[arg[attributes={name=class.name}; value=[com.atlassian.jira.workflow.function.issue.IssueCreateFunction]]]], function[attributes={type=class}; value=[arg[attributes={name=class.name}; value=[com.atlassian.jira.workflow.function.issue.IssueReindexFunction]]]], function[attributes={type=class}; value=[arg[attributes={name=eventTypeId}; value=[1]], arg[attributes={name=class.name}; value=[com.atlassian.jira.workflow.function.event.FireIssueEventFunction]]]]]]]]]]]]]
...

期望的输出: 获取所有属性和值,最好采用以下格式:

attribute name :   value

jira.updated.date : 1503954892468

jira.update.author.key : admin

1 个答案:

答案 0 :(得分:0)

以下脚本会 -

  • 找到所有meta元素
  • 使用name属性及其文字
  • 创建地图
  • 最后打印地图。

不包括xml字符串以避免大空间,无论如何你都拥有它。

def metas = new XmlSlurper().parseText(xml).'**'.findAll {it.name() == 'meta'}
def metaAttributeMap = metas.collectEntries{ [(it.@name):it.text()]}
metaAttributeMap.each {k,v -> println "$k : $v"}

您可以在线快速尝试 demo