Groovy 脚本 - 员工报告结构 - 循环 XML 以找到所需的领导者

Groovy Script - Employee reporting structure - Looping through XML to find required Leader

我有两个 xml 使用 <multimap> 节点组合在一起。第一个数据源发送员工和经理 ID 信息(节点),第二个数据源发送所有领导者 ID 信息(节点中仅列出领导者 ID,领导者可以是经理的经理或直接经理或 2-up/3-up )它们都组合在<multimap> 标签。

我想遍历 <multimap1> 节点的 <PerPerson>,检查经理 ID,直到在 中找到领导者 ID,一旦找到领导者 ID,就在员工记录(节点)中添加一个节点。

请帮忙!

XML 文件:

 <?xml version='1.0' encoding='UTF-8'?>
<multimap:Messages xmlns:multimap="http://sap.com/xi/XI/SplitAndMerge">
<multimap:Message1>    
  <PerPerson>
    <PerPerson>
    <empId>12345</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>67891</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
       </UserAccount>
    </userAccountNav>
    </PerPerson>
    <PerPerson>
    <empId>67891</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>12123</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
      </UserAccount>
    </userAccountNav>
    </PerPerson>
    <PerPerson>
    <empId>56789</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>12123</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
       </UserAccount>
    </userAccountNav>
    </PerPerson>
    <PerPerson>
    <empId>12123</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>67678</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
       </UserAccount>
    </userAccountNav>
    </PerPerson>
  </PerPerson>
</multimap:Message1>
<multimap:Message2>
    <rfc:ZZH_LEADER_WF_GET_APPROVERS.Response xmlns:rfc="urn:sap-com:document:sap:rfc:functions">
        <LEADER>12123</LEADER>
        <LEADER>23234</LEADER>
        <LEADER>34345</LEADER>
        <LEADER>56567</LEADER>
        <LEADER>67678</LEADER>      
    </rfc:ZZH_LEADER_WF_GET_APPROVERS.Response>
</multimap:Message2>
</multimap:Messages>

所需结果:在上面的员工和经理数据中,在标签内进行迭代,直到经理 ID 是 rfc / get approvers 列表中的领导者 ID 之一。一旦找到,在标签内添加带有 ID 的领导者 ID 标签

<?xml version='1.0' encoding='UTF-8'?>
  <PerPerson>
    <PerPerson>
    <empId>12345</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>67891</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
       </UserAccount>
    </userAccountNav>
    <leader>12123<leader>
    </PerPerson>
    <PerPerson>
    <empId>67891</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>12123</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
      </UserAccount>
    </userAccountNav>
    <leader>12123<leader>
    </PerPerson>
    <PerPerson>
    <empId>56789</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>12123</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
       </UserAccount>
    </userAccountNav>
    <leader>12123<leader>
    </PerPerson>
    <PerPerson>
    <empId>12123</empId>
    <userAccountNav>
      <UserAccount>
        <user>
          <User>
            <manager>
              <User>
                <mgrEmpId>67678</mgrEmpId>
              </User>
            </manager>
          </User>
        </user>
       </UserAccount>
    </userAccountNav>
    <leader>67678<leader>
    </PerPerson>
  </PerPerson>

我试过的代码

    map = message.getProperties();
   def body = message.getBody(java.lang.String) as String;
def messageLog = messageLogFactory.getMessageLog(message);

 def xml = new XmlParser().parseText(body)

    def ns = new groovy.xml.Namespace('http://sap.com/xi/XI/SplitAndMerge')
def rfcNs = new groovy.xml.Namespace('urn:sap-com:document:sap:rfc:functions')
   
//for fast search let map PERNR value to a node that contains it, like internal table
def leaderMap = xml[ns.Message1][0][rfcNs.get("ZHR_GET_AWARD_LEADERS.Response")][0].children().collectEntries{ [it.LEADER_LIST.item.text().replaceFirst("^0+(?!$)", ""), it] }

  
//itearte msg1 -> find entry in leaderMap -> add node
xml[ns.Message2][0].PerPerson[0].each{p->
def emp = p.PerPerson[0]
def leader = leaderMap[p.PerPerson.userAccountNav.UserAccount.user.User.manager.User.mgrEmpId.text()]
if(leader)
{
 //  def counter = counter + 1
   p.PerPerson.appendNode('leader', null, leader.text() )
}

}

错误:代码未根据匹配找到的经理 ID 过滤领导 ID

> java.lang.NoSuchMethodException: No signature of method:
> groovy.util.NodeList.appendNode() is applicable for argument types:
> (java.lang.String, null, java.lang.String) values: [leader, null, 000000710000008000000184000005020000053000000638000008750000090600001630000125800001341000014010000152800001623000019900000199300002413000030580000340200004157000051720000525300013698000159520001555000162800016170001647000206000021458000215180002278000249080002629400030650004117000417]

我在您的代码中发现了一些错误:

  1. NodeList 没有 appendNode 这就是发生错误的原因
  2. p 已经是 PerPerson 节点之一,可能会导致代码混乱
  3. ZHR_GET_AWARD_LEADERS.Response 标签在提供的 xml 中不存在,所以我改为 ZZH_LEADER_WF_GET_APPROVERS.Response

我做的是:

  1. 实例化 'Node' 使用 new Node(p, 'leader', leader.text()) 从而在 xml
  2. 中创建一个新节点
  3. 删除了对 children() 的调用并在收集到 leaderMap
  4. 之前添加了 collect { it }
  5. 删除了闭环内的 PerPerson 个调用
  6. 创建了查找员工领导的算法

groovyide.com/cpi代码

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.XmlUtil;

def Message processData(Message message) {
    def body = message.getBody(java.lang.String) as String
    def xml = new XmlParser().parseText(body)
    def ns = new groovy.xml.Namespace('http://sap.com/xi/XI/SplitAndMerge')
    def rfcNs = new groovy.xml.Namespace('urn:sap-com:document:sap:rfc:functions')

    // I HAD TO CHANGE THE LINE BELOW BECAUSE THE XML DIDN't HAVE "ZHR_GET_AWARD_LEADERS.Response"
    //for fast search let map PERNR value to a node that contains it, like internal table
    def leaderMap = xml[ns.Message2][0][rfcNs.get("ZZH_LEADER_WF_GET_APPROVERS.Response")][0]\
                        .collect { it }.collectEntries { [it.text().replaceFirst("^0+(?!$)", ""), it] }

    // All employee manager's, including the managers themselves
    def upManagers = xml[ns.Message1][0].PerPerson[0].collect { it }.collectEntries { p ->
        [p.empId.text(), p.userAccountNav.UserAccount.user.User.manager.User.mgrEmpId.text()]
    }

    // itearte msg1 -> find entry in leaderMap -> add node
    xml[ns.Message1][0].PerPerson[0].each { p ->
        def manager = p.userAccountNav.UserAccount.user.User.manager.User.mgrEmpId.text()
        def leader = leaderMap[manager]
        while (!leader && manager) {
            manager = upManagers[manager]
            leader = leaderMap[manager]
        }
        def node = new Node(p, 'leader', leader.text())
    }
    message.setBody(XmlUtil.serialize(xml[ns.Message1][0].PerPerson[0]))
    return message
}