1 2 Previous Next 21 Replies Latest reply on Jan 14, 2013 12:54 AM by steve.winter

    XPath with BE_XPath()

    steve.winter

      Hi all

       

      I need to access data from a remote XML feed, which I'm trying to do using an FM script and the BE plugin.

       

      At present I've got;

      Set Variable[$xml; Value:BE_GetURL("http://my.url.com/xmlfeed"; ""; "username"; "password")]

       

      So far so good, in the data viewier I get my variable correctrly set to the XML feed from the remote server, that looks like this:

       

      <Users xmlns="http://my.url.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instanc" xsi:schemaLocation="schema.xsd">

      <User>
      <UserId>123</UserId>

      <UserRole>TRADER</UserRole>

      <Title>Mr.</Title>

      <Firstname>Some</Firstname>

      <Surname>Person</Surname>

      <CompanyName>A Company</CompanyName>

      <TradingName>A Company</TradingName>

      <Address>
      <AddressLine1>123 Some Street</AddressLine1>

      <Town>London</Town>

      <Postcode>W1 2SQL</Postcode>

      <Country>United Kingdom</Country>

      <Telephone>908090808</Telephone>

      <Mobile>0808080808</Mobile>

      </Address>

      <ProductCategories>
      <Category>Clothing and Footwear</Category>

      <Category>Fashion and Design</Category>

      </ProductCategories>

      <ExpiryDate/>

      <Status>REQUESTED</Status>

      </User>

      </Users>

       

      Now when I try to use the BE_XPath function to access data within there, I'm not getting anywhere. I've tried;

      Set Variable[$addr; Value:BE_XPath ( $xml; "//AddressLine1" )]

      which I expected to set variable $addr to 123 Some Street

       

      Set Variable[$user; Value:BE_XPath ( $xml; "Users/User" )]

      from which I expected $user to end up containing the above XML block for the user (so pretty much all of it)

       

      Set Variable[$users; Value:BE_XPathAll ( $xml; "//User" )]

      which I expected would give me a list of (in this case only one) users

       

      I've worked with XPath before, but only within PHP and thought I understood how it works, but maybe not...? any tips...? pointers...? suggestions...?

       

      Cheers

      Steve

        • 1. Re: XPath with BE_XPath()
          comment

          The reason why "//AddressLine1" doesn't work is that the entire XML document lives in its own namespace (defined as an attribute of the Users element). This is easier to handle when using XSLT, because then you can define a prefix for the given namespace and call elements by their fully qualified name. With XPath, it's a bit more awkward - try:

           

          //*[local-name()="AddressLine1"]

           

          or the more strict:

           

          //*[local-name()="AddressLine1" and namespace-uri()='http://my.url.com']

           

           

           

          ---

          BTW, if your XML source is available through a GET request, why don't you simply import it directly using a XSLT stylesheet (and no plugin)?

           

          Message was edited by: Michael Horak

          • 2. Re: XPath with BE_XPath()
            steve.winter

            Hi Michael

             

            Thanks - that's a big help, in that I've now been able to extract individual node from the XML feed, but because I'm expecting that there will be multiple User nodes in the Users XML, I was hoping that I would be able to get the XML for each user into something which I could loop through, extracting the necessary data nodes from that XML.

             

            I tried

                 "//*"

            but that gave me all the data from the User node as a string of text, rather than a smaller piece of XML… any further guidance greatly appreciated…

             

            Cheers

            Steve

            • 3. Re: XPath with BE_XPath()
              beverly

              I don't know what you can do with the plugin, but in XSLT:

                xsl:value-of gives you the text (likely) of the node

                xsl:copy-of gives you the node (including all descendants)

               

              HTH,

               

              -- sent from my iPhone4 --

              Beverly Voth

              --

              • 4. Re: XPath with BE_XPath()
                comment

                steveWinter wrote:

                 

                I was hoping that I would be able to get the XML for each user into something which I could loop through, extracting the necessary data nodes from that XML.

                 

                That's exactly what XSLT will do for you (among other things).

                 

                 

                steveWinter wrote:

                 

                I tried

                     "//*Re: XPath with BE_XPath()"

                 

                That didn't come out too well, I am afraid.

                • 5. Re: XPath with BE_XPath()
                  steve.winter

                  Doh..! Let's try that again directly into the web app, rather than by email...

                   

                  I tried

                            "//*[local-name()='User']"

                  but that gave me all the data from the User node as a string of text, rather than a smaller piece of XML… any further guidance greatly appreciated…

                   

                  Cheers

                  Steve

                  • 6. Re: XPath with BE_XPath()
                    comment

                    Let me suggest a simpler example:

                     

                    <Users xmlns="http://my.url.com">
                        <User>
                        <UserId>001</UserId>
                        <Firstname>Adam</Firstname>
                        <Surname>Abrams</Surname>
                        <Address>
                            <AddressLine1>101 First Street</AddressLine1>
                            <City>Aspen</City>
                        </Address>
                        </User>
                        <User>
                        <UserId>002</UserId>
                        <Firstname>Betty</Firstname>
                        <Surname>Blue</Surname>
                        <Address>
                            <AddressLine1>22 Second Street</AddressLine1>
                            <City>Baltimore</City>
                        </Address>
                        </User>
                    </Users>
                    

                     

                     

                    Using the above XML source, the following XPath expression:

                     

                    //*[local-name()="User"][2]/*[local-name()="Firstname"]
                    

                     

                    should return "Betty",

                     

                    //*[local-name()="User"][1]/*[local-name()="Address"]
                    

                     

                    will return:

                     

                           101 First Street
                            Aspen
                        
                    

                     

                    i.e. the entire content of the Address node, and:

                     

                    //*[local-name()="User"][2]/*[local-name()="Address"]/*[local-name()="City"]
                    

                     

                    will return "Baltimore"

                     

                     

                    Hope this makes things clear. I urge you once again to switch to XSLT, as you will find parsing the document element-by-element extremely tedious.

                    • 7. Re: XPath with BE_XPath()
                      steve.winter

                      Michael

                       

                      At this stage I'll take any suggestions/advice etc - this seems like such a simple thing to do, and in PHP would take me about 5 lines of foreach($xml->Users->User as $user) { do stuff }...

                       

                      Using your simple example above, how would I extract each User, and then be able to access each of the nodes from within there...?

                       

                      Thanks for your advice so far...!

                       

                      Cheers

                      Steve

                      • 8. Re: XPath with BE_XPath()
                        comment

                        Have a look at the attached. Note that when specifying the XML source, you can also point to a URL.

                        • 9. Re: XPath with BE_XPath()
                          steve.winter

                          Michael

                           

                          That's genius stuff...!! thanks so much for this...

                           

                          One final question. In your example XML you have

                               <Users xmlns="http://my.url.com">

                           

                          Then in the XSL you have

                               <xsl:for-each select="my:Users/my:User">

                           

                          I presume the 'my' is the namespace reference...? so if my 'real' XML file has

                               <Users xmlns="http://www.thehelppeople.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instanc" xsi:schemaLocation="insurance.xsd">

                          then I would use

                               <xsl:for-each select="www:Users/www:User">

                           

                          Thanks again for all your help.

                           

                          Kind regards

                          Steve

                          • 10. Re: XPath with BE_XPath()
                            beverly

                            No, Steve, he has this in the XSLT:

                             

                            xmlns:my="http://my.url.com" exclude-result-prefixes="my"

                             

                            then the namespace-prefix is 'my:' for each of his elements.

                             

                            You must have the FILE called 'insurance.xsd', so that the xml can be validated against the XSD.

                             

                            Beverly

                            • 11. Re: XPath with BE_XPath()
                              comment

                              Beverly Voth wrote:

                               

                              You must have the FILE called 'insurance.xsd'

                               

                              I don't know about that - it works fine for me without it.

                              • 12. Re: XPath with BE_XPath()
                                steve.winter

                                Thanks Beverly - I spotted that about half a min after I'd added the reply...

                                 

                                Cheers

                                Steve

                                • 13. Re: XPath with BE_XPath()
                                  comment

                                  BTW, I have just noticed that the BE_XPath() function has an optional namespaceList parameter, so that using the example in post #6 anbove, you could have used =

                                   

                                  BE_XPath ( $XML ; "//my:User[2]/my:Firstname" ; "my=http://my.url.com" )
                                  

                                   

                                  to extract "Betty", etc. It's still not a real alternative to XSLT, but worth mentioning, IMHO.

                                  • 14. Re: XPath with BE_XPath()
                                    steve.winter

                                    Michael

                                     

                                    I agree that insurace.xsd doesn't seem to be need as although I do have access to that xsd, it's not in a location which makes it accessible, but it's working (almost) as required.

                                     

                                    Your next discovery about about being able to specify a name space with the BE_XPath function will be very useful in other areas, where I actualy need to be able to get a response code, and response message from other functionality that is implemented as part of this, so don't want to be creating records, but to be parsing the response...

                                     

                                    One issue that I'm unsure on how to solve. One of the nodes in the XML feed I receive for each User looks like this;

                                    <ProductCategories>

                                         <Category>Clothing and Footwear</Category>

                                         <Category>Fashion and Design</Category>

                                         <Category>... etc ...</Category>

                                    </ProductCategories>

                                     

                                    I need to get that into a single field as a return separated list. When I use

                                         <COL><DATA><xsl:value-of select="tmp:ProductCategories"/></DATA></COL>

                                    I get the desired data in the FM field, however with a line break before the first item, after the last item and white space before each item (some of which appear to be tab characters, others spaces). Do you know of a way to strip out all of that white space using the xsl...?

                                     

                                    One other question - do the xml and xsl both have to be actual 'files on disk', or should I be able to get this to work with each coming from a field or variable...? the later - from a variable would be most desireable, from a field acceptable, from a file something of a nusiance, particularly in the case of the XML...

                                     

                                    Thanks again for your excellent sample file and continued assistance with solving this issue - my client and I are both extremely gratefull :-)

                                     

                                    Cheers

                                    Steve

                                    1 2 Previous Next