Search code examples
javascriptajaxxmlsharepoint

Trouble extracting xml property from ajax response


I'm using SharePoint on Premises 2019 and I have an ajax request to a SharePoint list. The list has a preexisting column named attachments which contains images that were uploaded to it.

Now the ajax request to return elements of the list returns a xml response for the attachments column. The response

<feed
    xmlns="http://www.w3.org/2005/Atom"
    xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
    xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
    xmlns:georss="http://www.georss.org/georss"
    xmlns:gml="http://www.opengis.net/gml">
    <id>e3a2717c-932c-43a0-b1c6-f81a75329948</id>
    <title />
    <updated>2024-03-26T06:02:30Z</updated>
    <entry>
        <id>http://po/sites/pssm/_api/Web/Lists(guid'f80db476-8b0c-4a8b-b9b6-0516028525d5')/Items(25)/AttachmentFiles('contact.webp')</id>
        <category term="SP.Attachment" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
        <link rel="edit" href="Web/Lists(guid'f80db476-8b0c-4a8b-b9b6-0516028525d5')/Items(25)/AttachmentFiles('contact.webp')" />
        <title />
        <updated>2024-03-26T06:02:30Z</updated>
        <author>
            <name />
        </author>
        <content type="application/xml">
            <m:properties>
                <d:FileName>contact.webp</d:FileName>
                <d:FileNameAsPath m:type="SP.ResourcePath">
                    <d:DecodedUrl>contact.webp</d:DecodedUrl>
                </d:FileNameAsPath>
                <d:ServerRelativePath m:type="SP.ResourcePath">
                    <d:DecodedUrl>/sites/pssm/Lists/PoliceHomeAds/Attachments/25/contact.webp</d:DecodedUrl>
                </d:ServerRelativePath>
                <d:ServerRelativeUrl>/sites/pssm/Lists/PoliceHomeAds/Attachments/25/contact.webp</d:ServerRelativeUrl>
            </m:properties>
        </content>
    </entry>
</feed>

Here the image url can be found in the serverRelativeUrl tag of xml response.

This is my js loop statement that generates the tag.

  <a" href="' + objArray[i].AttachmentFiles.__deferred.uri + '">    </a>;

For now I'm using anchor tag just so I can see the results returned by the statement more clearly. If I use image tag, it just shows me the browser image default icon.

Do help. How can I display image?


Solution

  • The XML contains namespaces, so the most efficient way imho is Xpath. It allows you to use expressions to match nodes.

    Namespaces in XML are URIs. Aliases/prefixes are used to make a serialized XML document smaller and more human readable. However the following 3 elements can all be read as {http://www.w3.org/2005/Atom}feed:

    • <feed xmlns="http://www.w3.org/2005/Atom"/>
    • <a:feed xmlns:a="http://www.w3.org/2005/Atom"/>
    • <atom:feed xmlns:atom="http://www.w3.org/2005/Atom"/>

    fetchXML('https//...').then(
      (xmlDocument) => {
        // define a namespace resolver to map prefixes in the xpath 
        // expression to URIs matching the namespace definitions in the document
        const resolver = {
          lookupNamespaceURI: (prefix) => {
            const namespaces = {
              atom: 'http://www.w3.org/2005/Atom' 
            };
            return namespaces[prefix] || null;
          }
        }
      
        const output = document.querySelector('#output');
    
        // clear output
        output.textContent = '';
        
        // append nodes
        output.append(
           // fetch from XML
          ...fetchNodes('//atom:entry/atom:id', xmlDocument, resolver).map(
            (node) => {
              // create HTML nodes
              const li = document.createElement('li');
              const a = li.appendChild(document.createElement('a'));
              a.setAttribute('href', node.textContent);
              a.textContent = node.textContent;
              return li;
            }
          )
        );
      }
    );
    
    // helper function to fetch nodes/values
    function fetchNodes(expression, context, resolver) {
        // evaluate expression in context with resolver
        const xpathResult = (context.ownerDocument || context).evaluate(
          expression,
          context,
          resolver,
          XPathResult.ANY_TYPE,
          null
        );
        
        switch (xpathResult.resultType) {
          case XPathResult.BOOLEAN_TYPE :
            return xpathResult.booleanValue;
          case XPathResult.NUMBER_TYPE :
            return xpathResult.numberValue;
          case XPathResult.STRING_TYPE :
            return xpathResult.stringValue;
          default:
            const result = [];
            // iterate result an fill array
            let node = xpathResult.iterateNext();
            while (node) {
                result.push(node);
                node = xpathResult.iterateNext();
            }
            return result;
        }
    }
    
    
    async function fetchXML(url) {
      return (new DOMParser()).parseFromString(
        // await fetch(url)
        `<feed
        xmlns="http://www.w3.org/2005/Atom"
        xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
        xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
        xmlns:georss="http://www.georss.org/georss"
        xmlns:gml="http://www.opengis.net/gml">
        <id>e3a2717c-932c-43a0-b1c6-f81a75329948</id>
        <title />
        <updated>2024-03-26T06:02:30Z</updated>
        <entry>
            <id>http://po/sites/pssm/_api/Web/Lists(guid'f80db476-8b0c-4a8b-b9b6-0516028525d5')/Items(25)/AttachmentFiles('contact.webp')</id>
            <category term="SP.Attachment" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
            <link rel="edit" href="Web/Lists(guid'f80db476-8b0c-4a8b-b9b6-0516028525d5')/Items(25)/AttachmentFiles('contact.webp')" />
            <title />
            <updated>2024-03-26T06:02:30Z</updated>
            <author>
                <name />
            </author>
            <content type="application/xml">
                <m:properties>
                    <d:FileName>contact.webp</d:FileName>
                    <d:FileNameAsPath m:type="SP.ResourcePath">
                        <d:DecodedUrl>contact.webp</d:DecodedUrl>
                    </d:FileNameAsPath>
                    <d:ServerRelativePath m:type="SP.ResourcePath">
                        <d:DecodedUrl>/sites/pssm/Lists/PoliceHomeAds/Attachments/25/contact.webp</d:DecodedUrl>
                    </d:ServerRelativePath>
                    <d:ServerRelativeUrl>/sites/pssm/Lists/PoliceHomeAds/Attachments/25/contact.webp</d:ServerRelativeUrl>
                </m:properties>
            </content>
        </entry>
    </feed>`,
       'application/xml'
      );
    }
    <ul id="output"></ul>