Validating an HTML input string
If all you want to do is confirm that the input string consists of a sequence of &lt;...&gt; elements:


Split the string on the &lt; character using your favourite string splitter
The first element must be blank
Subsequent elements must contain exactly one &gt; character


The input string is valid if every element passes the tests above.

Example

String splitter

I am using the SQL#.String_Split4k streaming table-valued function from the free edition of the SQLCLR SQLsharp library by Solomon Rutzky.

If the input string might be longer than 4000 characters, the (less efficient) SQL#.String_Split function would be used instead (it handles strings up to 2GB).

Any efficient string splitter (T-SQL or otherwise) that can return empty elements correctly with a sequence number will work.

The example below shows the sort of output SQL#.String_Split4k returns.

The first parameter is the string to split. The second parameter is the delimiter. The third parameter (SplitOption) is set to 1, which means Keep Empty Elements.

SELECT
    SS.SplitNum,
    SS.SplitVal
FROM SQL#.String_Split4k(N'&lt;a&gt;&lt;b&gt;&lt;c&gt;', N'&lt;', 1) AS SS;


Output:


╔══════════╦══════════╗
║ SplitNum ║ SplitVal ║
╠══════════╬══════════╣
║        1 ║          ║
║        2 ║ a>       ║
║        3 ║ b>       ║
║        4 ║ c>       ║
╚══════════╩══════════╝


Table and test data

CREATE TABLE #T
(
    row_id integer IDENTITY PRIMARY KEY,
    string varchar(50) NOT NULL
);

INSERT #T 
    (string)
VALUES 
    ('&lt;html&gt;Hello World&lt;/html&gt;'),
    ('&lt;html&gt;&lt;Hello World&lt;/html&gt;'),
    ('&lt;html&gt;&lt;Hello World&gt;&lt;/html&gt;');


Solution

SELECT
    T.row_id,
    string = (SELECT TOP (1) T2.string FROM #T AS T2 WHERE T2.row_id = T.row_id),
    is_valid =
        MIN
        (
            CASE
                -- First element must be blank
                WHEN SS.SplitNum = 1 AND SS.SplitVal = N'' THEN 1
                WHEN SS.SplitNum = 1 THEN 0
                -- Other elements must contain exactly one &gt;
                WHEN SS.SplitVal NOT LIKE N'%&gt;%' THEN 0
                WHEN SS.SplitVal LIKE N'%&gt;%&gt;%' THEN 0
                -- Otherwise valid
                ELSE 1
            END
        )
FROM #T AS T
CROSS APPLY SQL#.String_Split4k(T.string, '&lt;', 1) AS SS
GROUP BY T.row_id
ORDER BY T.row_id;


Output

╔════════╦════════════════════════════╦══════════╗
║ row_id ║           string           ║ is_valid ║
╠════════╬════════════════════════════╬══════════╣
║      1 ║ &lt;html&gt;Hello World&lt;/html&gt;   ║        1 ║
║      2 ║ &lt;html&gt;&lt;Hello World&lt;/html&gt;  ║        0 ║
║      3 ║ &lt;html&gt;&lt;Hello World&gt;&lt;/html&gt; ║        1 ║
╚════════╩════════════════════════════╩══════════╝