Xpath matching expression gives two strings values - xslt

I have an requirement to extract below value.
<cidx:ReferenceInformation ReferenceType="DeliveryNoteNumber">
<cidx:DocumentReference>
<cidx:DocumentIdentifier>5004330471</cidx:DocumentIdentifier>
</cidx:DocumentReference>
</cidx:ReferenceInformation>
I am using the below Xpath expression and getting 2 values match.
Expression
/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='ShipNotice']/*[local-name()='ShipNoticeBody']/*[local-name()='ShipNoticeProperties']/*[local-name()='ReferenceInformation']/*[local-name()='DocumentReference']/*[local-name()='DocumentIdentifier']/text()
Output
<?xml version="1.0" encoding="UTF-8"?>
<result>
5004330471
0803692106
</result>
I have tested the Xpath in the online tool
[http://www.xpathtester.com/xpath][1]
Below is INPUT XML
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Header/>
<SOAP:Body>
<cidx:ShipNotice xmlns:cidx="urn:cidx:names:specification:ces:schema:all:4:0" Version="4.0">
<cidx:Header>
<cidx:ThisDocumentIdentifier>
<cidx:DocumentIdentifier>0000001113658104</cidx:DocumentIdentifier>
</cidx:ThisDocumentIdentifier>
<cidx:ThisDocumentDateTime>
<cidx:DateTime DateTimeQualifier="On">2015-01-22T20:15:35Z</cidx:DateTime>
</cidx:ThisDocumentDateTime>
<cidx:From>
<cidx:PartnerInformation>
<cidx:PartnerName>MOS Company</cidx:PartnerName>
<cidx:PartnerIdentifier Agency="AGIIS-EBID">1234567890123</cidx:PartnerIdentifier>
<cidx:AddressInformation>
<cidx:AddressLine>N. Lindbergh</cidx:AddressLine>
<cidx:CityName>Columbia</cidx:CityName>
<cidx:StateOrProvince>MO</cidx:StateOrProvince>
<cidx:PostalCode>63190</cidx:PostalCode>
<cidx:PostalCountry>US</cidx:PostalCountry>
</cidx:AddressInformation>
</cidx:PartnerInformation>
</cidx:From>
<cidx:To>
<cidx:PartnerInformation>
<cidx:PartnerName> DIV BOWLNG GR VERA</cidx:PartnerName>
<cidx:PartnerIdentifier Agency="AssignedByPapiNet">0001664057</cidx:PartnerIdentifier>
<cidx:ContactInformation>
<cidx:ContactName>2015</cidx:ContactName>
<cidx:ContactDescription>SeedYear</cidx:ContactDescription>
</cidx:ContactInformation>
<cidx:ContactInformation>
<cidx:ContactName>1024122440000</cidx:ContactName>
<cidx:ContactDescription>AGIIS-EBID</cidx:ContactDescription>
</cidx:ContactInformation>
<cidx:AddressInformation>
<cidx:AddressLine>17410 PIKE 291</cidx:AddressLine>
<cidx:CityName>BOWLING GREEN</cidx:CityName>
<cidx:StateOrProvince>MO</cidx:StateOrProvince>
<cidx:PostalCode>633343045</cidx:PostalCode>
<cidx:PostalCountry>US</cidx:PostalCountry>
</cidx:AddressInformation>
</cidx:PartnerInformation>
</cidx:To>
</cidx:Header>
<cidx:ShipNoticeBody>
<cidx:ShipNoticeProperties>
<cidx:ShipmentIdentification>
<cidx:DocumentReference>
<cidx:DocumentIdentifier>0803692106</cidx:DocumentIdentifier>
</cidx:DocumentReference>
</cidx:ShipmentIdentification>
<cidx:ShipDate>
<cidx:DateTime DateTimeQualifier="On">2015-01-22T00:00:00Z</cidx:DateTime>
</cidx:ShipDate>
<cidx:PurchaseOrderInformation>
<cidx:DocumentReference>
<cidx:DocumentIdentifier>PO8956234</cidx:DocumentIdentifier>
<cidx:ReferenceItem>000530</cidx:ReferenceItem>
</cidx:DocumentReference>
</cidx:PurchaseOrderInformation>
<cidx:TransportMethodCode Domain="UN-Rec-19">3</cidx:TransportMethodCode>
<cidx:ReferenceInformation ReferenceType="DeliveryNoteNumber">
<cidx:DocumentReference>
<cidx:DocumentIdentifier>5004330471</cidx:DocumentIdentifier>
</cidx:DocumentReference>
</cidx:ReferenceInformation>
<cidx:ReferenceInformation ReferenceType="BillOfLadingNumber">
<cidx:DocumentReference>
<cidx:DocumentIdentifier>0803692106</cidx:DocumentIdentifier>
</cidx:DocumentReference>
</cidx:ReferenceInformation>
<cidx:ShipNoticeDate>
<cidx:DateTime DateTimeQualifier="On">2015-01-22T20:15:35Z</cidx:DateTime>
</cidx:ShipNoticeDate>
</cidx:ShipNoticeProperties>
</cidx:ShipNoticeBody>
</cidx:ShipNotice>
</SOAP:Body>
</SOAP:Envelope>
Can anyone please advise how to get only this value?
<cidx:DocumentIdentifier>5004330471</cidx:DocumentIdentifier>

Looks like you need to test the ReferenceType attribute in the cidx:ReferenceInformation element:
/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='ShipNotice']/*[local-name()='ShipNoticeBody']/*[local-name()='ShipNoticeProperties']/*[local-name()='ReferenceInformation' and #ReferenceType='DeliveryNoteNumber']/*[local-name()='DocumentReference']/*[local-name()='DocumentIdentifier']
Note: This xpath can be cleaned up a lot if you can declare the namespaces and use prefixes in the path.
You could also clean it up using * for the prefix if you're using XPath 2.0...
/*:Envelope/*:Body/*:ShipNotice/*:ShipNoticeBody/*:ShipNoticeProperties/*:ReferenceInformation[#ReferenceType='DeliveryNoteNumber']/*:DocumentReference/*:DocumentIdentifier

Related

XSLT select, problem with double namespace

when I use this xslt inline template on a BizTalk map
<xsl:template name="Test2">
<xsl:param name="sale" />
<xsl:variable name="promo" select="//s1:Sale[s1:ItemID = $sale]/s1:RetailPriceModifier[#MethodCode='Promotion' and #VoidFlag='false' and s1:ReasonCode= 'TRANSACTION_DISCOUNT']"/>
<DISCOUNT_VALUE1><xsl:value-of select="$promo[1]/s1:Amount"/></DISCOUNT_VALUE1>
<DISCOUNT_VALUE2><xsl:value-of select="$promo[2]/s1:Amount"/></DISCOUNT_VALUE2>
<DISCOUNT_VALUE3><xsl:value-of select="$promo[3]/s1:Amount"/></DISCOUNT_VALUE3>
<DISCOUNT_VALUE4><xsl:value-of select="$promo[4]/s1:Amount"/></DISCOUNT_VALUE4>
<DISCOUNT_VALUE5><xsl:value-of select="$promo[5]/s1:Amount"/></DISCOUNT_VALUE5>
<DISCOUNT_VALUE6><xsl:value-of select="$promo[6]/s1:Amount"/></DISCOUNT_VALUE6>
<DISCOUNT_REASON1><xsl:value-of select="$promo[1]/s1:dtv:DiscountReasonCode"/></DISCOUNT_REASON1>
<DISCOUNT_REASON2><xsl:value-of select="$promo[2]/s1:dtv:DiscountReasonCode"/></DISCOUNT_REASON2>
<DISCOUNT_REASON3><xsl:value-of select="$promo[3]/s1:dtv:DiscountReasonCode"/></DISCOUNT_REASON3>
<DISCOUNT_REASON4><xsl:value-of select="$promo[4]/s1:dtv:DiscountReasonCode"/></DISCOUNT_REASON4>
<DISCOUNT_REASON5><xsl:value-of select="$promo[5]/s1:dtv:DiscountReasonCode"/></DISCOUNT_REASON5>
<DISCOUNT_REASON6><xsl:value-of select="$promo[6]/s1:dtv:DiscountReasonCode"/></DISCOUNT_REASON6>
</xsl:template>
I receive the following error:
Expected end of the expression, found ':'.
$promo[1]/s1:dtv -->:<-- DiscountReasonCode
Could you please tell me how to resolve this issue?
here an input example:
<RetailPriceModifier MethodCode="Promotion" VoidFlag="false">
<SequenceNumber>1</SequenceNumber>
<Amount Action="Subtract">1.98</Amount>
<PromotionID>3705:8604:</PromotionID>
<ReasonCode>DEAL</ReasonCode>
</RetailPriceModifier>
<RetailPriceModifier MethodCode="Promotion" VoidFlag="false">
<SequenceNumber>2</SequenceNumber>
<Amount Action="Subtract">0.38</Amount>
<PromotionID>3706:8605:</PromotionID>
<ReasonCode>DEAL</ReasonCode>
</RetailPriceModifier>
<RetailPriceModifier MethodCode="Promotion" VoidFlag="false">
<SequenceNumber>3</SequenceNumber>
<Amount Action="Subtract">0.40</Amount>
<PromotionID>TRANS_PCT_PROMPT</PromotionID>
<ReasonCode>TRANSACTION_DISCOUNT</ReasonCode>
<dtv:DiscountReasonCode>DC4</dtv:DiscountReasonCode>
</RetailPriceModifier>
the output should be:
<DISCOUNT_VALUE1>0.40</DISCOUNT_VALUE1>
<DISCOUNT_REASON1>DC4</DISCOUNT_REASON1>
thanks and regards
The DiscountReasonCode elements are in the dtv namespace.
Remove the sv1: prefix from those XPaths targeting the DiscountReasonCode.
The XPath should be: $promo[1]/dtv:DiscountReasonCode

QXmlStreamWriter, namespace and prefix

I am new to XML and trying to write the following xml using QXmlStreamWriter :
<S:Envelope xmlns:S="url1">
<S:Body>
<ns2:name1 xmlns:ns2="url2">
..
So far I have tried:
sw.writeNamespace("url1", "S");
sw.writeStartElement("url1", "Envelope");
sw.writeStartElement("url1", "Body");
sw.writeStartElement("url2", "name1");
sw.writeNamespace("url2", "ns2");
but the result is not what I expect:
<S:Envelope xmlns:S="url1">
<S:Body>
<n1:name1 xmlns:n1="url2">
..
As specified in the documentation, the defaut prefix n1 is used instead of ns2.
If I swap the last 2 lines, I have:
<S:Envelope xmlns:S="url1">
<S:Body xmlns:ns2="url2">
<ns2:name1>
..
What am I doing wrong?
From the documentation of QXmlStreamWriter:
you can bypass the stream writer's namespace support and use overloaded methods that take a qualified name instead.
That is, use this overloaded method: QXmlStreamWriter::writeStartElement.
I suggest you to modify your code like that:
sw.writeNamespace("url1", "S");
sw.writeStartElement("url1", "Envelope");
sw.writeStartElement("url1", "Body");
sw.writeStartElement("ns2:name1");
sw.writeNamespace("url2", "ns2");
This produces the result you have stated as desired:
<S:Envelope xmlns:S="url1">
<S:Body>
<ns2:name1 xmlns:ns2="url2">

How to store single result from XPath Extractor

I have a HTTP request that return the following XML
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:obterAtividadesResponse xmlns:NS1="http://www.multiplan.com.br/APL/CLIE/SN/BPM/v1">
<atividades>
<atividade>
<instancia>
<idInstancia>2024</idInstancia>
</instancia>
<idAtividade>12887</idAtividade>
<nomeProcesso>Nota Fiscal ao Pagamento - Resumido</nomeProcesso>
<nomeAtividade>Aprovar Pagamento</nomeAtividade>
<statusAtividade>Received</statusAtividade>
<statusInstancia>Active</statusInstancia>
<dataLimite>2017-09-13T16:08:44.994+00:00</dataLimite>
<snapshot>76</snapshot>
<dadosNegocio>
<name>pedido</name>
<value>4500529987</value>
</dadosNegocio>
</atividade>
</atividades>
</NS1:obterAtividadesResponse>
</soapenv:Body>
</soapenv:Envelope>
I'm trying to extract the idAtividade content with XPath Extractor and save the result on atividadeId variable, but it's saving it's value on atividadeId_1 as you can see in the debug sampler result below:
atividadeId=
atividadeId_1=12887
atividadeId_matchNr=1
I'm using the following xpath query:
//atividades/atividade/idAtividade/text()
Is there a way to make it work as I need it?
Thanks
You should check Return entire XPath fragment instead of text content? checkbox.
It will them take the only text using your expression. See manual.
Also consider using Regular Expression Extractor.
If you have more than one atividade instance in response you can use the following XPath expression to get the first match:
//atividades/atividade[1]/idAtividade/text()
Or alternatively you can select idAtividade node value where nomeAtividade equals to Aprovar Pagamento with something like:
//atividades/atividade[nomeAtividade/text()='Aprovar Pagamento']/idAtividade
However given you have only one atividade instance your expression should work fine, you can test it using "XPath Tester" mode of the View Results Tree listener.
See XPath Tutorial and XPath Language Reference for comprehensive information on XPath syntax, axes, functions, etc.
My mistake, my test had an BeanShell Preprocessor setting the value of atividadeId variable to blank and I didn't know it was being executing after each sampler.

Extract Formula (text) field while referencing an existing saved search using NetSuite WebServices

I am trying to extract NetSuite saved search results using webservices. In the response I am only seeing the normal fields(entered in the Results section) but not the Formula (Text) field.
Below is the image of the saved search results section.
Below is the request sent to NetSuite.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:platform_2014_2.webservices.netsuite.com" xmlns:platformMsgs="urn:messages_2014_2.platform.webservices.netsuite.com" xmlns:platformFaults="urn:faults_2014_2.platform.webservices.netsuite.com">
<soap:Header>
<urn5:preferences xmlns:urn5="urn:messages_2014_2.platform.webservices.netsuite.com">
<urn6:warningAsError xmlns:urn6="urn:messages_2014_2.platform.webservices.netsuite.com">false</urn6:warningAsError>
<urn7:disableMandatoryCustomFieldValidation xmlns:urn7="urn:messages_2014_2.platform.webservices.netsuite.com">false</urn7:disableMandatoryCustomFieldValidation>
<urn7:ignoreReadOnlyFields xmlns:urn7="urn:messages_2014_2.platform.webservices.netsuite.com">false</urn7:ignoreReadOnlyFields>
</urn5:preferences>
<urn8:searchPreferences xmlns:urn8="urn:messages_2014_2.platform.webservices.netsuite.com">
<urn9:bodyFieldsOnly xmlns:urn9="urn:messages_2014_2.platform.webservices.netsuite.com">true</urn9:bodyFieldsOnly>
<urn10:pageSize xmlns:urn10="urn:messages_2014_2.platform.webservices.netsuite.com">1000</urn10:pageSize>
<urn11:returnSearchColumns xmlns:urn11="urn:messages_2014_2.platform.webservices.netsuite.com">true</urn11:returnSearchColumns>
</urn8:searchPreferences>
</soap:Header>
<soap:Body>
<platformMsgs:search xmlns:platformMsgs="urn:messages_2014_2.platform.webservices.netsuite.com" xmlns="urn:messages_2014_2.platform.webservices.netsuite.com">
<platformMsgs:searchRecord xsi:type="ns1:CustomerSearchAdvanced" xmlns:ns1="urn:relationships_2014_2.lists.webservices.netsuite.com" savedSearchId="2469"/>
</platformMsgs:search>
</soap:Body>
The response I am seeing is below.
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<platformMsgs:documentInfo
xmlns:platformMsgs="urn:messages_2014_2.platform.webservices.netsuite.com">
<platformMsgs:nsId>WEBSERVICES_TSTDRV840553_091920161097968934683523704_57aaf0b</platformMsgs:nsId>
</platformMsgs:documentInfo>
</soapenv:Header>
<soapenv:Body>
<searchResponse
xmlns="urn:messages_2014_2.platform.webservices.netsuite.com">
<platformCore:searchResult
xmlns:platformCore="urn:core_2014_2.platform.webservices.netsuite.com">
<platformCore:status isSuccess="true"/>
<platformCore:totalRecords>2</platformCore:totalRecords>
<platformCore:pageSize>1000</platformCore:pageSize>
<platformCore:totalPages>1</platformCore:totalPages>
<platformCore:pageIndex>1</platformCore:pageIndex>
<platformCore:searchId>WEBSERVICES_TSTDRV840553_091920161097968934683523704_57aaf0b</platformCore:searchId>
<platformCore:searchRowList>
<platformCore:searchRow xsi:type="listRel:CustomerSearchRow"
xmlns:listRel="urn:relationships_2014_2.lists.webservices.netsuite.com">
<listRel:basic
xmlns:platformCommon="urn:common_2014_2.platform.webservices.netsuite.com">
<platformCommon:comments>
<platformCore:searchValue>test</platformCore:searchValue>
</platformCommon:comments>
<platformCommon:entityId>
<platformCore:searchValue>test c 97161</platformCore:searchValue>
</platformCommon:entityId>
<platformCommon:entityStatus>
<platformCore:searchValue internalId="13"/>
</platformCommon:entityStatus>
<platformCommon:internalId>
<platformCore:searchValue internalId="59951"/>
</platformCommon:internalId>
</listRel:basic>
</platformCore:searchRow>
<platformCore:searchRow xsi:type="listRel:CustomerSearchRow"
xmlns:listRel="urn:relationships_2014_2.lists.webservices.netsuite.com">
<listRel:basic
xmlns:platformCommon="urn:common_2014_2.platform.webservices.netsuite.com">
<platformCommon:comments>
<platformCore:searchValue>test</platformCore:searchValue>
</platformCommon:comments>
<platformCommon:entityId>
<platformCore:searchValue>test c 97162</platformCore:searchValue>
</platformCommon:entityId>
<platformCommon:entityStatus>
<platformCore:searchValue internalId="13"/>
</platformCommon:entityStatus>
<platformCommon:internalId>
<platformCore:searchValue internalId="59952"/>
</platformCommon:internalId>
</listRel:basic>
</platformCore:searchRow>
</platformCore:searchRowList>
</platformCore:searchResult>
</searchResponse>
</soapenv:Body>
I don't see any explanation/examples related to this in NetSuite help guide as well.
Is there any other way that we need to trigger the request for extracting formula fields? Any pointers would be greatly helpful.
Thanks
I've been looking into this same topic and I don't believe Web Services supports formula fields in the result set. There appears to be no mechanism for returning them in a statically defined SOAP response. In my case, I needed the following formula.
GREATEST({trandate},{lastmodifieddate},{linelastmodifieddate},{billingtransaction.trandate},{billingtransaction.lastmodifieddate},{billingtransaction.linelastmodifieddate})
It existed in my saved search and did not throw an error when referenced from SuiteTalk. However, the formula field was not present as a column in my result set. I had to include each individual field used in my formula in the saved search and then recreate the formula in code.
If you need to use a formula as part of your filter criteria (to apply to a saved search), it will need to be defined in the saved search itself. You will not be able to apply formula based filters via the SuiteTalk API.
TransactionSearchAdvanced customSearch = new TransactionSearchAdvanced()
{
savedSearchScriptId = "customsearch_[Your ID here]"
,
criteria = new TransactionSearch()
{
[Formula fields are NOT supported here]
}
};

Apache CXF client namespace is in element instead of envelope

The problem I'm having is with Apache CXF putting the namespace inside the element instead of soap envelope.
I used codegen maven plugin to generate the client code from WSDL.
Here are the namespaces in the WSDL:
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
When I fire a SOAP request I can see in logs that the following message has been sent:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:userRegistrationRequest xmlns:ns1="http://some.com/namespace1">
<InputParameter xmlns:ns2="http://some.com/namespace1">
<ns2:Message>
<ns2:Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<ns2:HashTable>
<ns2:Item key="action">
<ns2:Value>some_action</ns2:Value>
</ns2:Item>
</ns2:HashTable>
</ns2:Message>
</InputParameter>
</ns1:userRegistrationRequest>
</soap:Body>
The problem is that the Value element was null in my code when I constructed the message, but here it appears with XSI namespace.
What I was expecting to get is something like this (Value element should not be present and XSI should be in the envelope element):
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<ns1:userRegistrationRequest xmlns:ns1="http://some.com/namespace1">
<InputParameter xmlns:ns2="http://some.com/namespace1">
<ns2:Message>
<ns2:HashTable>
<ns2:Item key="action">
<ns2:Value>some_action</ns2:Value>
</ns2:Item>
</ns2:HashTable>
</ns2:Message>
</InputParameter>
</ns1:userRegistrationRequest>
</soap:Body>
Does anyone have an idea how to prevent the CXF from generating that empty Value element and put the namespace inside the soap envelope element?
Ok, so to answer my question. There are two aspects of this problem.
First, adding namespaces to the envelope element. It can be done by writting a custom interceptor and registering it in some early phase. Something like this:
import java.util.Map;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
public class MyInterceptor extends AbstractSoapInterceptor {
private Map<String, String> nsMap;
public MyInterceptor(Map<String, String> nsMap) {
super(Phase.USER_LOGICAL);
this.nsMap = nsMap;
}
public void handleMessage(SoapMessage message) throws Fault {
message.put("soap.env.ns.map", nsMap);
message.put("disable.outputstream.optimization", Boolean.TRUE);
}
}
I found the above solution here
Secondly, to remove empty value element an xsd should be changed to that the element has minOccurs="0" and nillable = "false".