4

I need to remove empty <p> tags from all rich text fields in the content tree:

<p>&nbsp;</p>

I've done nothing myself with Sitecore Powershell Extensions so far, so I am not sure if this is possible.

I've created a saveitempipeline so that this can't happen anymore, but we have a lot of fields with empty <p> tags so I'd like to remove them with SPE.

2 Answers 2

12

You can use the below script to remove all empty p/P tags (having space or &nbsp;).

This script uses the HtmlDecode method of System.Web.HttpUtility class to decode single or multiple occurrences of &nbsp; to an empty string and then Regex replaces p tags with or without spaces.

$items = Get-ChildItem "master:/sitecore/content" -Recurse -Language *

foreach($item in $items){
    Write-Host "Item  - " $item.Paths.Path
    foreach($field in $item.Fields){

        if($field.Type -eq "Rich Text"){

            $rawValue = $field.Value

            if($rawValue -like '*<p*'){
                $output = [System.Web.HttpUtility]::HtmlDecode($rawValue)
                $output =  $output -replace "(<(P|p)>)\s*(<\/(P|p)>)",'' #To remove <p></p> or <p> {HAVING SPACES IN BETWEEN} </p> or <P></P> or <P>  {HAVING SPACES IN BETWEEN}  </P>
                $output =  $output -replace "(<(P|p)\s*\/>)",''          #To remove self closed p tags e.g.  <p/> or <p         />

                $item.Editing.BeginEdit()
                $item.Fields[$field.Name].Value = $output
                $item.Editing.EndEdit()

                Write-Host "Field - " $field.Name 
                Write-Host ""
            }
        }
    }
}

Tested with

<p>p tag with text</p><p/><p /><p></p><div>hello</div><p>&nbsp;&nbsp;&nbsp;</p>

Output

<p>p tag with text</p><div>hello</div>
3

Here is another take at solving this problem.

  • Use the HtmlAgilityPack (included with Sitecore) to parse the document
  • Check for each required scenario with a function
  • Save some time by only looking at known fields

Test Html

<div>Here is something</div>
<p></p>
<p>&nbsp;</p>
<p>&nbsp; </p>
<p> &nbsp;</p>
<p>  &nbsp;&nbsp;</p>
<div>Something here<p>  &nbsp;&nbsp;</p></div>
<p>Here is something interesting</p>
<ul>
    <li></li>
</ul>
<p><span></span></p>
<p><span>Some text</span></p>

Sample Script

function Remove-EmptyPTag {
    param(
        [string]$Text
    )
    $htmlDocument = New-Object -TypeName HtmlAgilityPack.HtmlDocument
    $htmlDocument.LoadHtml($Text)
    $pNodes = $htmlDocument.DocumentNode.SelectNodes("//p")
    foreach($x in $pNodes) {
        # If the node is completely empty then we should remove
        if([string]::IsNullOrEmpty($x.InnerText)) {
            $x.Remove()
            continue
        }
        # If the node is only made up of spaces then we should remove
        if($x.InnerText -match "^(&nbsp;|\s)*$") {
            $x.Remove()
            continue
        }
    }
    # Found that once the p node is removed you ended up with some empty nodes in the final document.
    $count = $htmlDocument.DocumentNode.ChildNodes.Count
    $nodes = [HtmlAgilityPack.HtmlNode[]]::new($count)
    $htmlDocument.DocumentNode.ChildNodes.CopyTo($nodes, 0)
    foreach($node in $nodes) { 
        if([string]::IsNullOrWhiteSpace($node.InnerText)) {
            $htmlDocument.DocumentNode.RemoveChild($node)
        }
    }

    $htmlDocument.DocumentNode.OuterHtml
}

Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}" |
    ForEach-Object { $_.Content = Remove-EmptyPTag -Text $_.Content }
2
  • Nice one! but I think regex needs a small fix to handle another empty p scenarios where there is a space before &nbsp; or space between multiple &nbsp; Sep 7, 2019 at 21:27
  • Thanks Surya. Realized I needed the '|' pipe character to allow for any position. Sep 8, 2019 at 1:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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