Submit and vote on feature ideas.

Welcome to the new Parasoft forums! We hope you will enjoy the site and try out some of the new features, like sharing an idea you may have for one of our products or following a category.

Concatenating Xpath values

Options
LegacyForum
LegacyForum Posts: 1,664 ✭✭
edited December 2016 in SOAtest
Hey guys is there a way to take the xpath values given from a xml-databank (say Test 1:z0 & Test 1: z1) and concatenate or join them together for later use. Or possibly as a script? I looked through the scriptingAPI for a join or concat function, but I didn't look too hard .

Thanks in advance,

LeapTester
Tagged:

Comments

  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    LeapTester,

    It looks like the values you are trying to concatenate are coming from the same test (Test 1); a nice way of concatenating the values into one is by modifying the XPath you are using. Try something like this:

    /*[local-name(.)="Envelope" and namespace-uri(.)="http://schemas.xmlsoap.org/soap/envelope/"]/*[local-name(.)="Body" and namespace-uri(.)="http://schemas.xmlsoap.org/soap/envelope/"]/*[local-name(.)="getItemByIdResponse" and namespace-uri(.)="http://www.parasoft.com/wsdl/store-01/"]/*[local-name(.)="Result" and namespace-uri(.)="http://www.parasoft.com/wsdl/store-01/"]/*[local-name(.)="id" and namespace-uri(.)="" or local-name(.)="quantity_in_stock"]

    The part in bold shows what I've added to an automatically generated XPath. This concatenates the "id" and "quantity_in_stock" values into one. Let me know if this works with your setup.

    -Mike
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    sweet!!! thanks for the tip. I'll give it a try and let the community know.

    I should have recognized that and sorry for wasting bandwidth...

    thanks again,

    LeapTester
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    Hey Mike Thanks again. You've inspired me to try something a bit more slick than the "or". I am trying to parse a response where accounts and status' are part of a resposne node. I want to pull all the account which are active and use the result for further use. However i'm having an issue with an Xpath that I think should work.

    I tried this syntax on the xml snippet below, which passes the SoaTest validation check, but doesn't appear to match anything...

    Am I missing a slash?

    Thanks

    LeapTester

    /*/*/*/*/*/accountSearchResponse[accountStatus="ACTIVE"]/accountNumber

    CODE
    <?xml version="1.0" encoding="UTF-8"?>
    <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:Body>
     <accountSearchResponse xmlns="http://websvc.casino.adapter.csp.leapwireless.com">
      <AccountSearchResponseMsg>
       <searchResponse>
        <accountSearchResponse>
         <accountNumber>000102065327714</accountNumber>
         <lastname>JOHNSON</lastname>
         <firstName>DONNA</firstName>
         <middleInitial/>
         <accountStatus>ACTIVE</accountStatus>
         <accountName/>
        </accountSearchResponse>
       </searchResponse>
      </AccountSearchResponseMsg>
     </accountSearchResponse>
    </soapenv:Body>
    </soapenv:Envelope>
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    LeapTester,

    I'm currently looking into using something like this:

    CODE
    /*[local-name(.)="Envelope" and namespace-uri(.)="http://schemas.xmlsoap.org/soap/envelope/"]/*[local-name(.)="Body" and namespace-uri(.)="http://schemas.xmlsoap.org/soap/envelope/"]/*[local-name(.)="accountSearchResponse" and namespace-uri(.)="http://websvc.casino.adapter.csp.leapwireless.com"]/*[local-name(.)="AccountSearchResponseMsg" and namespace-uri(.)="http://websvc.casino.adapter.csp.leapwireless.com"]/*[local-name(.)="searchResponse" and namespace-uri(.)="http://websvc.casino.adapter.csp.leapwireless.com"]/*[local-name(.)="accountSearchResponse" and namespace-uri(.)="http://websvc.casino.adapter.csp.leapwireless.com"]/*[local-name(.)="accountStatus" and namespace-uri(.)="http://websvc.casino.adapter.csp.leapwireless.com"][.="ACTIVE"]


    I'll be able to update you with another XPath string tomorrow.

    -Mike
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    Hey big guy, no problems. i'm trying to work the predicate approach because i'm basically lazy and I like the short syntax involved. Any help is appreciated.

    Best,

    LeapTester
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    LeapTester,

    I'm attaching an example SOAtest project that uses your XML and is able to do what your looking for. I made two different tests that should be good examples for you to look at.

    Each example has an Edit tool to show you what was selected by the transformer. If you change the XML input so that "ACTIVE" is something else, you'll notice that the transformer doesn't select anything.

    Let me know if this is not what your looking for.

    -Mike
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options

    Am I missing a slash?

    Thanks

    LeapTester

    /*/*/*/*/*/accountSearchResponse[accountStatus="ACTIVE"]/accountNumber

    The general tactic of using a predicate to compare the value of a child element is sound.

    However, the XPath returns nothing because the XML elements of interest use namespaces. Therefore, you cannot use the /tagName syntax. You must use the /prefix:tagName syntax. Currently there is no way to map prefixes to namespaces, so the simplest XPath you can now create ignores namespaces by using /*:tagName.

    Here is an XPath to get what you want, simplified to find the element anywhere in the document instead of only if at a certain depth.

    //*:accountSearchResponse[*:accountStatus = "ACTIVE"]/*:accountNumber
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options

    LeapTester,

    It looks like the values you are trying to concatenate are coming from the same test (Test 1); a nice way of concatenating the values into one is by modifying the XPath you are using. Try something like this:

    /*[local-name(.)="Envelope" and namespace-uri(.)="http://schemas.xmlsoap.org/soap/envelope/"]/*[local-name(.)="Body&quot; and namespace-uri(.)="http://schemas.xmlsoap.org/soap/envelope/"]/*[local-name(.)="getItemByIdResponse&quot; and namespace-uri(.)="http://www.parasoft.com/wsdl/store-01/"]/*[local-name(.)="Result&quot; and namespace-uri(.)="http://www.parasoft.com/wsdl/store-01/"]/*[local-name(.)="id&quot; and namespace-uri(.)="" or local-name(.)="quantity_in_stock"]

    If you want to separate the values using a delimiter, then the simplest approach is to use an XPath with the string-join function. You don't need any scripting API.

    string-join(
    (
    //*:id,
    //*:quantity_in_stock
    ),
    "|")

    The first argument to string-join is a sequence that contains both the id and quantity_in_stock elements. string-join combines all values in the first argument -- a sequence of values (contained within parentheses) -- by concatenating them together, with each value separated by the second argument, in this case "|". So if you had an id value of "xyz" and quantity_in_stock of "57", the XPath would return "xyz|57".

    If you know you want just a fixed number of values, you could also use the concat function:

    concat(//*:id, "|", //*:quantity_in_stock)
  • LegacyForum
    LegacyForum Posts: 1,664 ✭✭
    Options
    string-join was added as part of XPath 2.0.

    Here is the documentation:

    http://www.w3.org/TR/xpath-functions/#func-string-join