Javascript 附加xml节点的Groovy脚本代码,采用15+;6K员工记录的小时数
下面的代码正在运行,但需要15个多小时才能执行6000个员工记录,是否有任何改进 我有两个员工记录结构(员工数据和员工福利),对于6000名员工中的每一位,我使用人员编号将其合并为单个xml(要检查xml结构,请检查我前面的问题-) 现在,当ID(multimap:Message1中的personIdExternal)在multimap:Message2中找到相同的ID/PERNR时,我必须在xml员工记录中追加一个节点/子节点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
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.*
元素。在此数组上调用findAll应扫描所有这些元素count(person)+count(emememployment)+count(personIdExternal)=10000*3
- 在主循环中,
都在毫无理由地构建嵌套的大型数组。例如,在这个表达式之后,xml.'**'.findAll{it.name()='ememployment'}。每个{
您的def perID=xml.'**'.findAll找到{it.personIdExternal.text()==p.personIdExternal.text}
等于perID
p
**的情况下构建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()
时,我也没有看到任何情况。。。