Javascript 附加xml节点的Groovy脚本代码,采用15+;6K员工记录的小时数

Javascript 附加xml节点的Groovy脚本代码,采用15+;6K员工记录的小时数,javascript,xml,groovy,xml-parsing,sap-cloud-platform,Javascript,Xml,Groovy,Xml Parsing,Sap Cloud Platform,下面的代码正在运行,但需要15个多小时才能执行6000个员工记录,是否有任何改进 我有两个员工记录结构(员工数据和员工福利),对于6000名员工中的每一位,我使用人员编号将其合并为单个xml(要检查xml结构,请检查我前面的问题-) 现在,当ID(multimap:Message1中的personIdExternal)在multimap:Message2中找到相同的ID/PERNR时,我必须在xml员工记录中追加一个节点/子节点 xml.'**'.findAll{it.name() == 'E

下面的代码正在运行,但需要15个多小时才能执行6000个员工记录,是否有任何改进

我有两个员工记录结构(员工数据和员工福利),对于6000名员工中的每一位,我使用人员编号将其合并为单个xml(要检查xml结构,请检查我前面的问题-)

现在,当ID(multimap:Message1中的personIdExternal)在multimap:Message2中找到相同的ID/PERNR时,我必须在xml员工记录中追加一个节点/子节点

 xml.'**'.findAll{it.name() == 'EmpEmployment'}.each{ p->

 def perID = xml.'**'.find{it.personIdExternal.text() == p.personIdExternal.text()} 
 def pernr = xml.'**'.find{it.PERNR.text() == '000'+perID.personIdExternal.text()}
 if(pernr != null)
 {    
       perID.appendNode {
       erpBenEligibility(pernr.PARDT.text()) }
  }

}  
 message.setBody(groovy.xml.XmlUtil.serialize(xml))
示例XML:

<?xml version='1.0' encoding='UTF-8'?>
<multimap:Messages xmlns:multimap="http://sap.com/xi/XI/SplitAndMerge">
<multimap:Message1>
<person>
 <person>
    <street>test_stree1</street>
    <city>test_city1</city>
    <state>test_state1</state>
    <EmpEmployment>
     <personIdExternal> 001 </personIdExternal>
    </EmpEmployment>
 </person>
 <person>
    <street>test_stree2</street>
    <city>test_city2</city>
    <state>test_state2</state>
     <EmpEmployment>
     <personIdExternal> 002 </personIdExternal>
    </EmpEmployment>
 </person>
 <person>
    <street>test_stree3</street>
    <city>test_city3</city>
    <state>test_state3</state>
     <EmpEmployment>
     <personIdExternal> 003</personIdExternal>
     </EmpEmployment>
 </person>
</person>
</multimap:Message1>
<multimap:Message2>
<rfc:ZHR_GET_EMP_BENEFIT_DETAILS.Response xmlns:rfc="urn:sap- 
    com:document:sap:rfc:functions"> 
 <phone>
  <home>
   <phone>number1</phone>
  </home> 
  <PERNR> 001 </PERNR>
  <PARDT>#### 1 ####</PARDT>
  <home>
   <phone>number2</phone>
  </home> 
  <PERNR> 002 </PERNR>
  <PARDT>#### 2 ####</PARDT>
  <home>
   <phone>number3</phone>
  </home> 
  <PERNR> 003 </PERNR>
  <PARDT>#### 3 ####</PARDT>
</phone> 
</rfc:ZHR_GET_EMP_BENEFIT_DETAILS.Response xmlns:rfc="urn:sap-com:document:sap:rfc:functions">    
</multimap:Message2>
</multimap:Messages>

测试街1
测试城市1
测试状态1
001
测试街2
测试城市2
测试状态2
002
测试应力3
测试城市3
测试状态3
003
第一
001
#### 1 ####
2号
002
#### 2 ####
3号
003
#### 3 ####

代码中的一些主要问题:

  • 使用
    **
    访问器。如果message1中有10000名
    人员
    ,则
    xml.*
    将返回一个数组,其中包含
    count(person)+count(emememployment)+count(personIdExternal)=10000*3
    元素。在此数组上调用findAll应扫描所有这些元素
  • 在主循环中,
    xml.'**'.findAll{it.name()='ememployment'}。每个{
    都在毫无理由地构建嵌套的大型数组。例如,在这个表达式之后,
    def perID=xml.'**'.findAll找到{it.personIdExternal.text()==p.personIdExternal.text}
    您的
    perID
    等于
    p
您的代码仍然与xml示例不对应

因此,我将做一些假设来说明如何在不使用
**的情况下构建gpath。

让我们使用如下xml:


001
000001
#### 1 ####
这是构建大型xml消息的代码部分:

def count=60000//为了测试,让我们创建包含60K元素的xml
def msg=''
'''+
(1..计数)。收集{“”\
${String.format('%03d',it)}
“”“}.join()+
'''  
'''+
(1..计数)。收集{“”\
${String.format('%06d',it)}
####${it}####
“”“}.join()+
'''  
'''
现在是改进的变换算法:

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

def t = System.currentTimeMillis()
def ns = new groovy.xml.Namespace('http://sap.com/xi/XI/SplitAndMerge')

//for fast search let map PERNR value to a node that contains it
def pernrMap=xml[ns.Message2][0].phone[0].children().collectEntries{ [it.PERNR.text(), it] }

//itearte msg1 -> find entry in pernrMap -> add node
xml[ns.Message1][0].person[0].person.each{p->
    def emp = p.EmpEmployment[0]
    def pernr = pernrMap['000'+emp.personIdExternal.text()]
    if(pernr) emp.appendNode('erpBenEligibility', null, pernr.PARDT.text() )
}
groovy.xml.XmlUtil.serialize(xml)
println "t = ${(System.currentTimeMillis()-t)/1000} sec"

即使对于msg1和msg2中的60k元素,它也能在不到1秒的时间内完成转换。

非常感谢@daggett,在我的示例中,为了简单起见,我没有给出message2结构的确切结构,它还有一个名称sp
*****子节点,就像在前面的示例中一样***
我尝试了'def ns2=new groovy.xml.Namespace('urn:sap com:document:sap:rfc:functions')def pernrMap=xml[ns.message2.ns2][0].LT_0167[0].children().collectEntries{[it.PERNR.text(),it]}`但它不起作用。请提供帮助。编辑了我的示例xml以在message2块中添加节点,请检查。尝试了不同的方法来访问子节点,就像在我上面的评论中一样,还尝试了def pernrMap=xml[ns.message2][0]。ns2[0]。phone[0]。children().collectEntries{[it.PERNR.text(),it]}其中,ns2是上述注释中message2块中的命名空间。请忽略上述注释中的LT_0167[0],它等于phone[0]。错误表明我仅以“xml[ns.message2][0].phone[0].children()”访问空对象。由于名称空间节点。您必须在代码中声明另一个名称空间,如下所示:
def rfcNs=new groovy.xml.namespace('urn:sap com:document:sap:rfc:functions')
再次感谢您。我这样做了,但如何在message2&name空间中导航。我做了以下操作,但它不起作用。
def pernrMap=xml[ns.message2.rfcNs][0]。电话[0].children()如果你能接受api,你可以选择一个更快的XML库,比如:可以做很多修改。但是首先-停止使用
“**”。
-最好使用精确的gpath(完整或相对)。并且您的代码与之前几乎被删除的问题不对应。请编辑此问题并添加简短的xml示例以执行此代码。感谢您的回答@daggett。我在我的问题中添加了示例xml示例,正如我在上一个问题中所问,我的xml中有“和”标记,不允许我使用精确的gpath,所以我使用“**”遍历到我想要的节点。非常感谢您提供的任何帮助。再次感谢您。在xml中,我没有看到从代码引用的
PARDT
元素。在您的xml中,当
it.PERNR.text()==“000”+perID.personIdExternal.text()
时,我也没有看到任何情况。。。