<p>Say I have:</p>

<pre><code>&lt;ul&gt;
    &lt;li id="x"&gt;
        &lt;a href="x"&gt;x&lt;/a&gt;
    &lt;/li&gt;

    &lt;li id="y"&gt;
        &lt;a href="y"&gt;y&lt;/a&gt;

        &lt;ul&gt;
            &lt;li id="z"&gt;
                &lt;a href="z"&gt;z&lt;/a&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
</code></pre>

<p>I want to add a class value to all the list items that are the parents of z. So, I want to modify y but not x.</p>

<p>Obviously, I can parse this into some kind of associative array and then recurse backwards. Any ideas how I can do it with just text processing (string replacing, regular expression, etc)?</p>

<p>Thanks!</p>

[{'answer_id': 56958, 'author': 'hasseg', 'author_id': 4111, 'author_profile': 'https://Stackoverflow.com/users/4111', 'pm_score': 0, 'selected': False, 'text': "<p>I suggest you parse it into a DOM and recurse backwards like you were thinking. Regular expressions don't work very well for nested structures with arbitrary nesting levels.</p>\n"}, {'answer_id': 56960, 'author': 'Simon Keep', 'author_id': 1127460, 'author_profile': 'https://Stackoverflow.com/users/1127460', 'pm_score': 2, 'selected': False, 'text': '<p>I would use XSLT. You can specify to search for nodes that are ancestors of z .</p>\n'}, {'answer_id': 57076, 'author': 'VolkerK', 'author_id': 4833, 'author_profile': 'https://Stackoverflow.com/users/4833', 'pm_score': 2, 'selected': False, 'text': '<p>xpath has an ancestor-axis which includes all ancestors of the current context node.</p>\n\n<p>//*[@id="z"]/ancestor::li</p>\n\n<p><strong>*</strong> any element<br />\n<strong>[@id="z"]</strong> that has an attribute <i>id</i> with the value <i>z</i> (since the attribute is id there can(/should be) only be one such element)<br />\n<strong>/ancestor::li</strong> all <i>li</i> elements that are ancestors of that</p>\n\n<p>see also: <a href="https://www.w3schools.com/xml/xpath_axes.asp" rel="nofollow noreferrer">https://www.w3schools.com/xml/xpath_axes.asp</a></p>\n'}, {'answer_id': 57118, 'author': 'DaveP', 'author_id': 3577, 'author_profile': 'https://Stackoverflow.com/users/3577', 'pm_score': 0, 'selected': False, 'text': "<p>\n\n\n\n\n</p>\n\n<p>Will add the attribute only to elements with a descendent element of 'z'. </p>\n"}, {'answer_id': 57210, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': '<p>Thanks for the input. I figured it was impossible without parsing (or using xsl, etc)... Oh well.</p>\n'}, {'answer_id': 58329, 'author': 'jelovirt', 'author_id': 2679, 'author_profile': 'https://Stackoverflow.com/users/2679', 'pm_score': 1, 'selected': False, 'text': '<p>Example of the whole XSLT:</p>\n\n<pre><code>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt;\n\n  &lt;xsl:variable name="ancestors" select="descendant::li[@id = \'z\']/ancestor::li"/&gt;\n\n  &lt;xsl:template match="li"&gt;\n    &lt;xsl:copy&gt;\n      &lt;!-- test if current li is in the $ancestors node-list --&gt;\n      &lt;xsl:if test="count($ancestors | .) = count($ancestors)"&gt;\n        &lt;xsl:attribute name="class"&gt;ancestor&lt;/xsl:attribute&gt;\n      &lt;/xsl:if&gt;\n      &lt;xsl:apply-templates select="node() | @*"/&gt;\n    &lt;/xsl:copy&gt;\n  &lt;/xsl:template&gt;\n\n  &lt;xsl:template match="node() | @*"&gt;\n    &lt;xsl:copy&gt;\n      &lt;xsl:apply-templates select="node() | @*"/&gt;\n    &lt;/xsl:copy&gt;\n  &lt;/xsl:template&gt;\n\n&lt;/xsl:stylesheet&gt;\n</code></pre>\n'}, {'answer_id': 58365, 'author': 'John Sheehan', 'author_id': 1786, 'author_profile': 'https://Stackoverflow.com/users/1786', 'pm_score': 0, 'selected': False, 'text': '<p>This is a good fit for jQuery if that\'s available to you.</p>\n\n<pre><code>$("#z").parent().parent().addClass("foo");\n</code></pre>\n'}, {'answer_id': 59496, 'author': 'VolkerK', 'author_id': 4833, 'author_profile': 'https://Stackoverflow.com/users/4833', 'pm_score': 0, 'selected': False, 'text': "<p>In addition to John Sheehan's anwser:<br />\nWith JQuery I'd rather use\n<br/><code>$('#z').parents('li').addClass('myClass');</code><br/>\nthan relying on the actual structure.</p>\n"}]
['https://Stackoverflow.com/questions/56946', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/-1/']