As an alternative to MCL's solution, here a fully Jsoup based one:
First, here's how Jsoup see's your html:
org.jsoup.nodes.TextNode: Hi everyone. This is a
org.jsoup.nodes.Element: <em>dead end.</em>
org.jsoup.nodes.TextNode: Do not go!
All three nodes are children of the <p>...</p> element.
And here's the (very verbose) code:
final String html = "<p> Hi everyone. This is a <em>dead end.</em> Do not go!</p>";
Document doc = Jsoup.parseBodyFragment(html); // Parse html into a document
Element pTag = doc.select("p").first(); // Select the p-element (there's just one)
// Text before 'em'-tag
TextNode preEM = (TextNode) pTag.childNode(0);
preEM.text(preEM.text().replace("This is a", "This is not a"));
// Text after 'em'-tag
TextNode postEM = (TextNode) pTag.childNode(2);
postEM.text("You may go!");
System.out.println(pTag); // Print result
Output:
<p> Hi everyone. This is not a <em>dead end.</em>You may go!</p>
This will keep all html formatting and / or will work in full documents.