Parse the XML and update anchor tags?

Viewed 137
   <description>
    <div class="field field-name-field-image field-type-image field-label- 
    hidden"><div class="field- items"><div class="field-item even"><a 
    href="/news/news/vg"><img 
    typeof="foaf:Image" src=""  width="220" height="147" alt="Police car- 
    sign" /></a></div></div></div><div class="field field- 
    name-body field-type-text-with-summary field-label-hidden"><div 
    class="field-items"><div 
    class="field-item even" property="content:encoded"><p> SOME TEXT </p> 
    </div></div></div>
 </description>

I am reading XML and parsing it wants to update all anchor tags in that XML: In the above eg, I want to append the domain name in a tag. If href attribute does not start with HTTPS or HTTP or www. I want to append the base URL to the href attribute.

How do I parse this HTML and search for anchor tag update it and return that Updated HTML?

2 Answers

Here is a solution that leverages DOMParser in order to properly parse the HTML and update the anchor tags:

const string = `<description>
    <div class="field field-name-field-image field-type-image field-label-
    hidden"><div class="field- items"><div class="field-item even"><a
    href="/news/news/vg"><img
    typeof="foaf:Image" src=""  width="220" height="147" alt="Police car-
    sign" /></a></div></div></div><div class="field field-
    name-body field-type-text-with-summary field-label-hidden"><div
    class="field-items"><div
    class="field-item even" property="content:encoded"><p> SOME TEXT </p>
    </div></div></div>
 </description>`;

const baseURL = 'https://www.example.com';
const regex = /^(http|https|www)/;

const parser = new DOMParser;
const parsed = parser.parseFromString(string, 'text/html');

function updateHTML({ childNodes }) {
  childNodes.forEach(child => [updateLink, updateHTML].forEach(x => x(child)));
}

function updateLink(node) {
  if (node instanceof HTMLAnchorElement) {
    const href = node.getAttribute('href');
    !regex.test(href) && node.setAttribute('href', [baseURL, href].join(''));
  }
}

updateHTML(parsed.body);

console.log(parsed.body.innerHTML);

If you're using Node.js this doesn't work because DOMParser doesn't exist, then you have to use a third party library. This is how you could do with the jsdom library (install it with npm i jsdom):

const jsdom = require('jsdom');
const { JSDOM } = jsdom;

const string = `<description>
    <div class="field field-name-field-image field-type-image field-label-
    hidden"><div class="field- items"><div class="field-item even"><a
    href="/news/news/vg"><img
    typeof="foaf:Image" src=""  width="220" height="147" alt="Police car-
    sign" /></a></div></div></div><div class="field field-
    name-body field-type-text-with-summary field-label-hidden"><div
    class="field-items"><div
    class="field-item even" property="content:encoded"><p> SOME TEXT </p>
    </div></div></div>
 </description>`;

const baseURL = 'https://www.example.com';
const regex = /^(http|https|www)/;

const parsed = new JSDOM(string);

function updateHTML({ childNodes }) {
  childNodes.forEach(child => [updateLink, updateHTML].forEach(x => x(child)));
}

function updateLink(node) {
  if ('href' in node) {
    const href = node.getAttribute('href');
    !regex.test(href) && node.setAttribute('href', [baseURL, href].join(''));
  }
}

updateHTML(parsed.window.document.body);

console.log(parsed.window.document.body.innerHTML);

As I understand your want to handle your href link. So, for that you can simply use javascript for that and for that you need to just pass url inside this function and if url won't contain any protocol it will automatically http protocol with your url.

const addHttpUrl = (url) => {
    if (!/^(?:f|ht)tps?\:\/\//.test(url)) {
        url = "http://" + url;
    }
    return url;
}
Related