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>
2
  • What does this have to do with Salesforce?
    – Adrian Larson
    Apr 24, 2016 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, 2016 at 17:28

2 Answers 2

2

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));
2
  • 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.
    – Gerrit-K
    Mar 7, 2018 at 14:17
  • Yes parsing is better. I Should change to *? though. Will investigate.
    – Adrian Larson
    Mar 7, 2018 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.

2
  • 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, 2016 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, 2016 at 13:56

Not the answer you're looking for? Browse other questions tagged .