在服务器端 NetSuite 中从 AutoTask 中导航 XML



我正在研究某人的NetSuite帐户和他们的AutoTask帐户之间的集成。它从AutoTask接收数据,在NetSuite中创建记录,然后将其中一些数据传递回AutoTask。AutoTask的工作方式似乎是,我必须删除收到的XML的一部分,对其进行更改,然后将更新的块直接发布回系统中,否则它会删除任何未包含的内容。因此,在收到XML作为文本后,我使用函数nlapiStringToXML()将其转换为XML对象:

var xmlObj = nlapiStringToXML(xmlString);

我对数据进行了一些测试以获得所需的数据。下面是收到的 XML 的示例:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<queryResponse xmlns="http://autotask.net/ATWS/v1_5/">
<queryResult>
<ReturnCode>1</ReturnCode>
<EntityResults>
<Entity xsi:type="Ticket">
<id>54606</id>
<UserDefinedFields>
<UserDefinedField>
<Name>3rd Party Case Number</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Check in Text Single Line</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Escalation Case Number</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Additional Max Hours</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Additional Pay Rate</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Check In</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Check In MultiLine</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Check in Numeric</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Check Out</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Closing Notes</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN HD Name You Closed With</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Manager On Duty</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Max Hours/Devices</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Pay Mode</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Pay Rate</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Provider Cell Number</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Provider Name</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Return Tracking #</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Scheduled Date and Time</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Status</Name>
</UserDefinedField><UserDefinedField>
<Name>FN Total Amount</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FN Work Order ID</Name>
</UserDefinedField>
<UserDefinedField>
<Name>FOLLOW-UP NEEDED</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Kaseya Alert ID</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Kaseya Ticket ID</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Netsuite Case Internal Id</Name>
<Value>-2</Value>
</UserDefinedField>
<UserDefinedField>
<Name>Netsuite Case Number</Name>
</UserDefinedField>
<UserDefinedField>
<Name>New HW SN Number</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Old HW SN Number</Name>
</UserDefinedField>
<UserDefinedField>
<Name>RMA</Name>
</UserDefinedField>
<UserDefinedField>
<Name>Sales Order</Name>
</UserDefinedField>
<UserDefinedField>
<Name>SB OLO?</Name>
</UserDefinedField>
</UserDefinedFields>
<AccountID xsi:type="xsd:int">000</AccountID>
<AllocationCodeID xsi:type="xsd:int">00000000</AllocationCodeID>
<CreateDate xsi:type="xsd:dateTime">2018-04-12T08:49:54.323</CreateDate>
<CreatorResourceID xsi:type="xsd:int">29682898</CreatorResourceID>
<Description xsi:type="xsd:string">Integration Testing</Description>
<DueDateTime xsi:type="xsd:dateTime">2018-04-13T08:47:00</DueDateTime>
<IssueType xsi:type="xsd:int">17</IssueType>
<LastActivityDate xsi:type="xsd:dateTime">2018-04-12T08:50:11.1</LastActivityDate>
<Priority xsi:type="xsd:int">1</Priority>
<AssignedResourceID xsi:type="xsd:int">00000000</AssignedResourceID>
<AssignedResourceRoleID xsi:type="xsd:int">00000000</AssignedResourceRoleID>
<Source xsi:type="xsd:int">8</Source>
<Status xsi:type="xsd:int">1</Status>
<SubIssueType xsi:type="xsd:int">282</SubIssueType>
<TicketNumber xsi:type="xsd:string">T00000000.0000</TicketNumber>
<Title xsi:type="xsd:string">Integration Testing</Title>
<FirstResponseDueDateTime xsi:type="xsd:dateTime">2018-04-12T12:49:54.323</FirstResponseDueDateTime>
<ResolvedDueDateTime xsi:type="xsd:dateTime">2018-04-13T08:49:54.323</ResolvedDueDateTime>
<ServiceLevelAgreementID xsi:type="xsd:int">1</ServiceLevelAgreementID>
<Resolution xsi:type="xsd:string"/><PurchaseOrderNumber xsi:type="xsd:string"/>
<TicketType xsi:type="xsd:int">2</TicketType>
<ChangeInfoField1 xsi:type="xsd:string"/>
<ChangeInfoField2 xsi:type="xsd:string"/>
<ChangeInfoField3 xsi:type="xsd:string"/>
<ChangeInfoField4 xsi:type="xsd:string"/>
<ChangeInfoField5 xsi:type="xsd:string"/>
<TicketCategory xsi:type="xsd:int">3</TicketCategory>
<ExternalID xsi:type="xsd:string"/>
</Entity>
</EntityResults>
<EntityResultType>ticket</EntityResultType>
<Errors/>
<EntityReturnInfoResults>
<EntityReturnInfo>
<EntityId>54606</EntityId>
<DatabaseAction>None</DatabaseAction>
<DuplicateStatus>
<Found>false</Found>
<MatchInfo/>
<Ignored>false</Ignored>
</DuplicateStatus>
<Message/>
</EntityReturnInfo>
</EntityReturnInfoResults>
</queryResult>
</queryResponse>
</soap:Body>
</soap:Envelope>

我需要的是"实体"元素,在我的测试中,这是获取我需要的东西的方法:

var eObj = xmlObj.getElementsByTagName("Entity")[0];

但是,这会导致在服务器端执行时出现以下错误:

Java class "org.apache.xerces.dom.DeepNodeListImpl" has no public instance field or method named "0"

使用 NetSuite 的调试器来检查并弄清楚,看起来我得到的是一个测试字符串而不是一个 XML 对象:

eObj ==> {string} org.apache.xerces.dom.DeepNodeListImpl@239776f9

我已通过以下途径来获取所需的块:

var eObj = xmlObj.childNodes.firstChild.childNodes.firstChild.childNodes.firstChild.childNodes.firstChild.childNodes.firstChild.getNextSibling().firstChild;

我知道NetSuite有XML导航方法,但我发现它们不可靠。上面的方法假设所有内容将始终处于相同的确切位置,我不喜欢这样,因为如果返回的值随着新值或删除的值而更改,这将中断。特别是考虑到我需要拉出UserDefinedFields元素并运行子元素并更新其中的一些。我打算运行,检查"名称"是否与某些值匹配,然后将"值"标签添加到"UserDefinedField"元素以进行匹配。但是鉴于我看到的这种结构(它无视调试器中显示的有关对象结构的内容),我对如何循环访问这些子元素、找到需要更新的内容并完成任务感到困惑。这是我计划使用的,它似乎在浏览器控制台中工作:

for (var i = 0; i < eObj.getElementsByTagName("UserDefinedField").length; i++) {
if (eObj.getElementsByTagName("UserDefinedField")[i].getElementsByTagName("Name")[0].innerHTML == "FIELD_NAME") {
var vObjArr = eObj.getElementsByTagName("UserDefinedField")[i].getElementsByTagName("Value");
if (_tools.isEmpty(vObjArr) || vObjArr.length == 0) {
var vObjA = xmlObj.createElement("Value");
var vObjB = xmlObj.createTextNode("VALUE");
vObjA.appendChild(vObjB);
eObj.getElementsByTagName("UserDefinedField")[i].appendChild(vObjA);
} else {
eObj.getElementsByTagName("UserDefinedField")[i].getElementsByTagName("Value")[0].innerHTML = "VALUE";
}
}
if (/* additional values checks here*/) {
// do stuff
}
}

面对呈现给我的新现实,我不知道如何改变这一点。

而不是:

var eObj = xmlObj.getElementsByTagName("Entity")[0];

使用这个:

var eObj = xmlObj.getElementsByTagName("Entity").item(0)

仅仅因为返回对象是一个 DeepNodeListImpl,并且该类实现了一个返回指定索引处节点的方法项(int index)。它还有一个返回节点列表长度的getLength()。有关更多说明,请参阅此处的文档。

希望它会有所帮助。

最新更新