1

I have below HTML tag and i need to extract TAG child tag and its element.

<h3 class="large lheight20 margintop10">
<a href="https://google.com" class="marginright5 link linkWithHash detailsLink">
<span>get the content</span>
</a>

</h3>

I want to extract following string from the code.

 <a href="https://google.com" class="marginright5 link linkWithHash detailsLink">
    <span>get the content</span>
    </a>

I have tried the following but it does not work.

<h3[^<>]*class="large lheight20 margintop10"[^<>]*>(?<content>.*?)</h3>

closed as off-topic by Adrian Larson, Phil Hawthorn, Sebastian Kessel, Ratan Paul, Himanshu Apr 24 '16 at 18:50

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Programming questions not specific to Salesforce are off-topic here, but can be asked on Stack Overflow." – Adrian Larson, Phil Hawthorn, Sebastian Kessel, Ratan Paul, Himanshu
If this question can be reworded to fit the rules in the help center, please edit the question.

  • What does this have to do with Salesforce? – Adrian Larson Apr 24 '16 at 16:29
  • @adrian larson this have to do with salesforce. i am getting response from http request in HTML string from apex class and i have to extract text from it. – MIX DML Apr 24 '16 at 17:28
1

I was able to use the following pattern:

(?si)<h3[^>]+?>(.*)<\/h3>

Explanation:

  • (?si)
    • The s flag indicates that . should match newline characters.
    • Might as well use the i flag to make it case insensitive.
  • <h3[^>]+?>
    • Match the opening tag.
  • (.*)
    • Match all characters as match group 1.
  • <\/h3>
    • Match the closing tag.

Here is the script I used in Execute Anonymous:

String markup = '<h3 class="large lheight20 margintop10">\n' +
    '<a href="https://google.com" class="marginright5 link linkWithHash detailsLink">\n' +
    '<span>get the content</span>\n' +
    '</a>\n\n</h3>';
Matcher regex = Pattern.compile('(?si)<h3[^>]+?>(.*)<\\/h3>').matcher(markup);
system.debug(regex.find());
system.debug(regex.group(1));
  • Note that this will match multiple elements as one, e.g. <h3><a>...</a></h3><h3><b>...</b></h3> will be a single match with the group <a>...</a></h3><h3><b>...</b> due to the greedyness of (.*). If you want to avoid that, you can use a ? after *, i.e. (.*?), to enforce lazy matching, but you're probably better off with a solution that uses a parser like the one in the answer from Derek F. – Griddo Mar 7 '18 at 14:17
  • Yes parsing is better. I Should change to *? though. Will investigate. – Adrian Larson Mar 7 '18 at 14:39
2

Regular expressions work on regular languages, but HTML is not a regular language. So, while you can do some limited extraction of html using a regexp, regexps are not the right tool for the job.

Instead, I'd suggest using the Dom.Document class and the Dom.XmlNode class

A brief example to get you going

Dom.Document inDoc = new Dom.Document();
inDoc.load(htmlStringInput);

Dom.XmlNode root = inDoc.getRootElement();

Dom.XmlNode aTag = root.getChildElement('a', null);
Dom.XmlNode spanTag = aTag.getChildElement('span', null);

System.debug('extracted hyperlink: ' + aTag.getAttributeValue('href', null));
System.debug('extracted link text: ' + spanTag.getText());

I'm not exactly sure how you'd go about getting the string representation of the link tag (from the Dom.XmlNode) once you extracted it from the root, and I don't have the ability to play around with it today. I'll try to keep this in mind and see if I can work something out tomorrow if you truly need the entire content (attributes and children) of the link tag instead of the href and span text.

  • Thank you so much I am getting error System.XmlException: Failed to parse XML due to: entity reference name can not contain character =' (position: TEXT seen ...ight="1" src="tracking.-st.com/h/v2/ns-sa?nw=1&amp;siteUrl=... @70:84)" there are some unsupported character for XML. how to remove all. – MIX DML Apr 25 '16 at 2:48
  • That error message doesn't seem complete (missing the illegal character, assuming the character is printable). If you're getting this from an httpResponse, are you passing the result of getBodyDocument() into the load() method of the Dom.Document()? I don't see any obvious invalid character sequences, so I don't have any ideas beyond that. This might be the start of another question. – Derek F Apr 25 '16 at 13:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.