Join us this Friday for AI in Action at the Virtual Happy Hour! This free virtual event is open to all—enroll now on Academy and don’t miss out.

 

How to programmatically manipulate XhtmlString?

Vote:
 

Hi,

I have a situation where I need to update a bit of text in an XhtmlString programatically.  I want to replace an old value with a new value.  The value to be replaced is also the first "fragment" in the XhtmlString.

Currently the XhtmlString is composed of multiple fragments- some are simple HTML text, some are images, and some are additional blocks added into the XhtmlString.  I am trying to update just the first fragment and set it to a new bit of HTML.

Here's what I'm trying:

var clone = myBlock.CreateWritableClone() as MyBlock;
if (clone != null && clone.MainBody != null && clone.MainBody.Fragments.Any())
{
    // MainBody is an XhtmlString
    clone.MainBody.Fragments.RemoveAt(0);

    // value to replace- the first "fragment" of text
    var replaceValue = clone.MainBody.Fragments.First().InternalFormat;

    // replacement value html
    var newValue = @"<p>some new value</p>";

    var newBody = clone.MainBody.ToInternalString().Replace(replaceValue, newValue);
    clone.MainBody = new XhtmlString(newBody);

    // save
    _contentRepository.Save((IContent)clone, SaveAction.Publish, AccessLevel.NoAccess);
}

When I run this, however, I seem to lose the blocks that have been added to the rich text.

What is the proper way to go about replacing 1 fragment of an XhtmlString with another?

#229753
Edited, Oct 22, 2020 20:15
Vote:
 

I found the solution.  What you need to do is:

  1. Create a new XhtmlString
  2. Loop through the old XhtmlString's fragments, and append each fragment to the new XhtmlString.  Skip the one you are trying to manipulate and inject a different fragment instead.
  3. Save the IContent housing the XhtmlString

So in my case, the first fragment was static HTML and had a typo in it.  We needed to find this and fix it, so the pseudo-algorithm looked like this:

var clone = myBlock.CreateWritableClone () as MyBlock;
if (clone != null && clone.MainBody != null && clone.MainBody.Fragments.Any ()) {

    // replace first fragment with new bit of HTML:
    var targetVal = "<h1>Hello World</h1>";
    var newXhtmlStringValue = new XhtmlString ();
    newXhtmlStringValue.Fragments.Add (new StaticFragment (targetVal));;

    // skip first fragment and add the rest to the new xhtml string
    clone.MainBody.Fragments.RemoveAt (0); // purge first item from old body
    foreach (var fragment in clone.MainBody.Fragments) {
        newXhtmlStringValue.Fragments.Add (fragment);
    }

    // set the main body over to the new xhtml string
    clone.MainBody = newXhtmlStringValue;

    // save
    _contentRepository.Save ((IContent) clone, SaveAction.Publish, AccessLevel.NoAccess);
}
#229801
Oct 23, 2020 13:00
Vote:
 

My initial suggestion would be something like this:

var clone = myBlock.CreateWritableClone () as MyBlock;
if (clone != null && clone.MainBody != null) 
{
    var oldText = clone.MainBody.ToInternalString();
    var newText = oldtext.Replace("old", "new");
    clone.MainBody = new XhtmlString(newText);
    _contentRepository.Save ((IContent) clone, SaveAction.Publish, AccessLevel.NoAccess);
}

But your approach looks safer. Maybe I will mess up blocks, personalization or some other stuff I did not think of?

#229834
Oct 24, 2020 17:51
Vote:
 

Correct Tomas, converting the entire XhtmlString to an internal string, and then parsing it back will break any dynamic fragments inside (personalized, blocks, etc).  This could possibly be a bug on the XhtmlString constructor.  I couldn't find any other way around this except to copy the fragments out one by one and inject a new static fragment in the target location.

#229899
Oct 26, 2020 12:12
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.