---
title: "XHTMLStrictFilter"
type: "forum-thread"
url: "https://www.webforum.nu/amne/dotnet/78828-xhtmlstrictfilter"
topic: ".NET"
topic_url: "https://www.webforum.nu/amne/dotnet"
author: "Web-Tor"
published: "2003-06-03T19:22:47.000Z"
updated: "2005-06-14T13:41:28.000Z"
replies: 24
views: 1626
page: 1
pages: 2
language: "sv-SE"
site: "webForum — webforum.nu"
rights: "Upphovsrätten till varje inlägg tillhör dess författare."
attribution: "Citera som: webForum, https://www.webforum.nu/amne/dotnet/78828-xhtmlstrictfilter"
---

# XHTMLStrictFilter

_Sida 1 av 2._

## #1 — Web-Tor, 2003-06-03T19:22Z

**1\.** Jag använda följande kod för få min sida validerad som XHTML:

```
/* 
* Written by Mark Pasternak, [email]mark.pasternak@universum.se[/email] 
* Feel free to modify 
*/ 
using System; 
using System.IO; 
using System.Text.RegularExpressions; 

namespace Consolidate 
{ 
	/// <summary> 
	/// Response Filter that modifies the ASP.NET output so it can validate against the XHTML 1.1 Strict standard. 
	/// Two things are modified: 
	/// 1. The form name attribute is removed. Warning, this may break JavaScript code! 
	/// 2. The viewstate is wrapped in a div element. 
	/// </summary> 
	public class XHTMLStrictFilter : Stream 
	{ 
		private Stream _sink; 
		private long _position; 

		private static Regex _regForm = new Regex([b][red]"<form .*name=.* .*>"[/red][/b], RegexOptions.Compiled|RegexOptions.IgnoreCase); 
		private static Regex _regNameReplace = new Regex("name=[^ ]*", RegexOptions.Compiled|RegexOptions.IgnoreCase); 
		private static Regex _regViewState = new Regex("<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", RegexOptions.Compiled|RegexOptions.IgnoreCase); 

		private bool _formFix; 
		private bool _viewStateFix; 

		public XHTMLStrictFilter(Stream sink) 
		{ 
			_sink = sink; 
		} 

		// The following members of Stream must be overriden. 
		public override bool CanRead 
		{ 
			get { return true; } 
		} 

		public override bool CanSeek 
		{ 
			get { return true; } 
		} 

		public override bool CanWrite 
		{ 
			get { return true; } 
		} 

		public override long Length 
		{ 
			get { return 0; } 
		} 

		public override long Position 
		{ 
			get { return _position; } 
			set { _position = value; } 
		} 

		public override long Seek(long offset, System.IO.SeekOrigin direction) 
		{ 
			return _sink.Seek(offset, direction); 
		} 

		public override void SetLength(long length) 
		{ 
			_sink.SetLength(length); 
		} 

		public override void Close() 
		{ 
			_sink.Close(); 
		} 

		public override void Flush() 
		{ 
			_sink.Flush(); 
		} 

		public override int Read(byte[] buffer, int offset, int count) 
		{ 
			return _sink.Read(buffer, offset, count); 
		} 

		// The Write method actually does the filtering. 
		public override void Write(byte[] buffer, int offset, int count) 
		{ 
			byte[] data; 

			if(!_formFix || !_viewStateFix) 
			{ 
				string htmlOutput = System.Text.UTF8Encoding.UTF8.GetString(buffer); 
				int length = htmlOutput.Length; 
				if(!_formFix && _regForm.IsMatch(htmlOutput)) 
				{ 
					string formMatch=_regForm.Match(htmlOutput).Value; 
					htmlOutput=Regex.Replace(htmlOutput, formMatch, _regNameReplace.Replace(formMatch, ""), RegexOptions.IgnoreCase); 
					_formFix=true; 
				} 
				if(!_viewStateFix && _regViewState.IsMatch(htmlOutput)) 
				{ 
					string viewStateMatch=_regViewState.Match(htmlOutput).Value; 
					htmlOutput=Regex.Replace(htmlOutput, viewStateMatch, "<div>"+viewStateMatch+"</div>", RegexOptions.IgnoreCase); 
					_viewStateFix=true; 
				} 
				data = System.Text.UTF8Encoding.UTF8.GetBytes(htmlOutput); 
				count -= length - htmlOutput.Length; 
			} 
			else 
			{ 
				data = new byte[count]; 
				Buffer.BlockCopy(buffer, offset, data, 0, count); 
			} 
			_sink.Write(data, 0, count); 
		} 
	} 
}
```

Den ska bl.a. ta bort **name="foo"** ur alla form-taggar. Problemet är att det inte funkar om action-attributet innehåller ett frågetecken:

```
<!-- Funkar -->
<form name="foo" action="test.html">

<!-- Funkar inte -->
<form name="foo" action="test.html?var=1">
```

Hur kan man lösa det?

**2\.** Vad jag förstår går det att lägga till ovanstående klass i global.asax så att alla sidor körs genom XHTML-filtrer. Hur gör jag det?

Permalänk: https://www.webforum.nu/p/78828

## #2 — Web-Tor, 2003-06-04T16:28Z

Ok! Jag vet att det är en rejäl bit kod men någon borde väl vara duktigt på Regex. :q

Problemet borde väl ligga i den fetmarkerade biten ovanför?

Permalänk: https://www.webforum.nu/p/1073898

## #3 — icaaq, 2003-06-04T17:39Z

1\.

```
[red]
private static Regex _regForm = new Regex("<form .*name=\".*\">", RegexOptions.Compiled|RegexOptions.IgnoreCase);
[/red]
```

2\.

```
[red]
		protected void Application_EndRequest(Object sender, EventArgs e)
		{
			Response.Filter = new XHTMLStrictFilter(Response.Filter);
		}[/red]
```

helt otestat ;)

Permalänk: https://www.webforum.nu/p/1073951

## #4 — Web-Tor, 2003-06-04T20:39Z

1\. Ingen skillnad. :(
2\. /r Det funkade om jag lade den i **Application_BeginRequest**. :)

Permalänk: https://www.webforum.nu/p/1074131

## #5 — Web-Tor, 2003-06-09T14:54Z

Jag ställer väl frågan på ett annat sätt då:
Hur gör jag för att matcha **name=""** när det ligger i form-tagg?

Permalänk: https://www.webforum.nu/p/1079695

## #6 — Web-Tor, 2003-06-16T11:47Z

Ingen som kan något om reguljära uttryck alltså?

Permalänk: https://www.webforum.nu/p/1084044

## #7 — DavidB, 2003-06-17T07:13Z

kolla här:
<http://www.webeye.nu/default2.asp?que=asp/default.asp&exec=asp/artiklar/asp_11.asp>

Det e ju dock asp men jag antar att det är samma för asp.net

Permalänk: https://www.webforum.nu/p/1084694

## #8 — spango, 2003-06-17T10:43Z

Alltså... nu kan ju inte jag C#, men jag gör ett försök ändå. Jag tror att regexpen i sin nuvarande form kan vara något för girig, om det ser ut så här:
*@"\<form .\*name=(.).\*?\\1 .\*\>"* 
skulle det kanske funka. :OO

Permalänk: https://www.webforum.nu/p/1084819

## #9 — Web-Tor, 2003-06-17T12:37Z

Det var inte fel på min RegEx överhuvudtaget.
Jag fick hjälp på ett annat forum :r och svaret låg i den här raden.

```
// Gammal och fel
htmlOutput=Regex.Replace(htmlOutput, formMatch, _regNameReplace.Replace(formMatch, "")

// Ny och rätt
htmlOutput=Regex.Replace(htmlOutput,_regNameReplace.Match(formMatch).value,"")
```

Inte för att jag fattar varför men nu funkar det. :)

Permalänk: https://www.webforum.nu/p/1087991

## #10 — Web-Tor, 2003-06-18T08:08Z

Jag har hittat ett fel till. :(
Den här gången är det div-taggarna runt ViewState som inte funkar om ViewState-fältet innehåller ett plus (+).

Funkar
\<input type="hidden" name="\__VIEWSTATE" value="dDwtMTE5MjY4" /\>

Funkar inte
\<input type="hidden" name="\__VIEWSTATE" value="**\+**dDwtMTE5MjY4" /\>

Snälla, hjälp!

Permalänk: https://www.webforum.nu/p/1088583

## #11 — Web-Tor, 2003-06-19T09:25Z

Nu har hag fått hjälp att lösa detta och felet var att alla RegEx-tecken (+, ?, \\, ^, m.m.) tolkades som just RegEx.

```
// Fel
htmlOutput=Regex.Replace(htmlOutput, viewStateMatch, "<div>"+viewStateMatch+"</div>");

// Rätt
htmlOutput=Regex.Replace(htmlOutput, "<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", "<div>"+viewStateMatch+"</div>");
```

Det kan vara bra att veta för alla andra som använder det här filtret. ;)

Permalänk: https://www.webforum.nu/p/1089364

## #12 — icaaq, 2004-02-11T09:29Z

Jag skulle vilja kicka igång denna tråd igen och undrar om man kan ta bort alla border="0" genom detta filter.

någon med stora regEx kunskaper kanske kan ge mig ett filter som funkar ;)

mv icaaq

Permalänk: https://www.webforum.nu/p/1272971

## #13 — icaaq, 2004-02-11T09:51Z

Fixade det själv :)

```
[red]
/*
* Written by Mark Pasternak, [email]mark.pasternak@universum.se[/email]
* Feel free to modify
*/
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace NineteenDecember
{
	/// <summary>
	/// Response Filter that modifies the ASP.NET output so it can validate against the XHTML 1.1 Strict standard.
	/// Two things are modified:
	/// 1. The form name attribute is removed. Warning, this may break JavaScript code!
	/// 2. The viewstate is wrapped in a div element.
	/// </summary>
	public class XHTMLStrictFilter : Stream
	{
		private Stream _sink;
		private long _position;

		private static Regex _regForm = new Regex("<form .*name=.* .*>", RegexOptions.Compiled|RegexOptions.IgnoreCase);
		private static Regex _regNameReplace = new Regex("name=[^ ]*", RegexOptions.Compiled|RegexOptions.IgnoreCase);
		private static Regex _regViewState = new Regex("<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", RegexOptions.Compiled|RegexOptions.IgnoreCase);
		// Tillagd 2004-02-11. Tar bort alla border="0"
		private static Regex _regBorder = new Regex("border=[^ ]*", RegexOptions.Compiled|RegexOptions.IgnoreCase);

		private bool _formFix;
		private bool _viewStateFix;
		private bool _borderFix;

		public XHTMLStrictFilter(Stream sink)
		{
			_sink = sink;
		}

		// The following members of Stream must be overriden.
		public override bool CanRead
		{
			get { return true; }
		}

		public override bool CanSeek
		{
			get { return true; }
		}

		public override bool CanWrite
		{
			get { return true; }
		}

		public override long Length
		{
			get { return 0; }
		}

		public override long Position
		{
			get { return _position; }
			set { _position = value; }
		}

		public override long Seek(long offset, System.IO.SeekOrigin direction)
		{
			return _sink.Seek(offset, direction);
		}

		public override void SetLength(long length)
		{
			_sink.SetLength(length);
		}

		public override void Close()
		{
			_sink.Close();
		}

		public override void Flush()
		{
			_sink.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			return _sink.Read(buffer, offset, count);
		}

		// The Write method actually does the filtering.
		public override void Write(byte[] buffer, int offset, int count)
		{
			byte[] data;

			if(!_formFix || !_viewStateFix || !_borderFix)
			{
				//string htmlOutput = System.Text.UTF8Encoding.UTF8.GetString(buffer);
				string htmlOutput = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(buffer);
				int length = htmlOutput.Length;
				if(!_formFix && _regForm.IsMatch(htmlOutput))
				{
					string formMatch=_regForm.Match(htmlOutput).Value;
					
					// *** Borttagen 03-06-17 ***
					// *** htmlOutput=Regex.Replace(htmlOutput, formMatch, _regNameReplace.Replace(formMatch, ""), RegexOptions.IgnoreCase);
					htmlOutput=Regex.Replace(htmlOutput, _regNameReplace.Match(formMatch).Value,"", RegexOptions.IgnoreCase);
					_formFix=true;
				}
				if(!_viewStateFix && _regViewState.IsMatch(htmlOutput))
				{
					string viewStateMatch=_regViewState.Match(htmlOutput).Value;
					htmlOutput=Regex.Replace(htmlOutput, "<input type=\"hidden\" name=\"__VIEWSTATE\" value=\".*\" />", "<div>"+viewStateMatch+"</div>", RegexOptions.IgnoreCase); 
					_viewStateFix=true;
				}
				// Tillagd 2004-02-11. Tar bort alla border="0"
				if(!_borderFix && _regBorder.IsMatch(htmlOutput))
				{
					string formMatch=_regBorder.Match(htmlOutput).Value;
					htmlOutput=Regex.Replace(htmlOutput, _regBorder.Match(formMatch).Value,"", RegexOptions.IgnoreCase);
					_borderFix=true;
				}
				//data = System.Text.UTF8Encoding.UTF8.GetBytes(htmlOutput);
				data = System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(htmlOutput);
				count -= length - htmlOutput.Length;
			}
			else
			{
				data = new byte[count];
				Buffer.BlockCopy(buffer, offset, data, 0, count);
			}
			_sink.Write(data, 0, count);
		}
	}
}
[/red]
```

*Det kan vara bra att veta för alla andra som använder det här filtret.*  ;)

mv icaaq

Permalänk: https://www.webforum.nu/p/1272985

## #14 — maqe, 2005-06-09T15:36Z

Använder det filtret som finns i den senaste tråden men jag får endå fel på hidden taggarna för viewstate \<input type="hidden" name="\__EVENTTARGET" value="" /\> samt \<script language="javascript" type="text/javascript"\> ... Är inte det filtret komplett?

Permalänk: https://www.webforum.nu/p/1628856

## #15 — maqe, 2005-06-09T18:00Z

\__EVENTTAGET och \__EVENTARGUMENT fick jag lägga till i koden bara men 2 language="javascript" skulle jag även vilja ta bort ... man får väl göra en regexp för det med antar jag?

Permalänk: https://www.webforum.nu/p/1628908

## #16 — maqe, 2005-06-10T06:22Z

Verkar som att \__dopostback funktionen har både languge och type? \<script language="javascript" type="text/javascript"\> Är det ingen som använder detta filter längre och har en nyare version. Jag löste javascript felet i \__doPostBack genom att ta bort language attributet men det är ju inte så vettigt kanske...

Permalänk: https://www.webforum.nu/p/1629042

## #17 — Web-Tor, 2005-06-10T06:29Z

Poängen med scriptet är ju att få sidan att validera enligt XHTML standarden. Då kan du ju ta bort language-attributet. ;)

Permalänk: https://www.webforum.nu/p/1629043

## #18 — maqe, 2005-06-10T06:38Z

Näe jag vet det men eftersom \__doPostBack innehåller både language och type så var jag tvungen att ta bort language för att endast får type kvar :) ... förstår inte varför min \__doPostBack function innehåller både language och type ... kanske för att jag kör episerver?

Permalänk: https://www.webforum.nu/p/1629046

## #19 — maqe, 2005-06-10T07:41Z

Verkar som att man får ersätta \__dopostback på något sätt ... nån som vet hur?

Permalänk: https://www.webforum.nu/p/1629068

## #20 — maqe, 2005-06-13T09:36Z

Nu verkar jag ha fått allt att fungera förutom att jag måste ha name attributet i formuläret. När jag plockar bort name attributet i form taggen och bara har id så smäller \__dopostback funktionen med felet att \__EVENTTARGET är null eller inget objekt. Skulle vara otroligt tacksam om nåon som själv kör detta kunde vara lite hjälpsam.

Permalänk: https://www.webforum.nu/p/1630001

---

Tråden på webben: https://www.webforum.nu/amne/dotnet/78828-xhtmlstrictfilter  
Nästa sida: https://www.webforum.nu/amne/dotnet/78828-xhtmlstrictfilter/page2.md
