There are multiple ways to achieve this.
Filtering key with predicate on xquery expression
Use an xquery expression with a predicate to filter to <p> nodes that contain a <k> child node with the desired string literal (i.e. "Attribute Name 2") using the value() function:
SELECT m.xml.value('(/p[k/text()="Attribute Name 2"]/v/text())[1]',N'varchar(max)')
from m
See it demonstrated in this sqlfiddle.
And if there is a possibility of unicode characters in the data, prefix the xquery string with N and select the value as nvarchar(max):
SELECT m.xml.value(N'(/p[k/text()="Attribute Name 2"]/v/text())[1]',N'nvarchar(max)')
from m
Select key and value as fields and apply WHERE condition
Borrowing from the second query in this answer, CROSS APPLY can be used in a sub-query with .nodes() to select the text of the <k> and <v> nodes as fields using value().
Then in the outer-query, a WHERE condition can be added to restrict <p> nodes to only those with a <k> with text Attribute Name 2.
select [key], value
from (
select x.value('(k/text())[1]','varchar(max)') as [key],
x.value('(v/text())[1]','varchar(max)') as value
FROM m
CROSS APPLY xml.nodes('//p') as p(x)
) as Result
where [key] = 'Attribute Name 2'
See a demonstration of this in this SQL fiddle.
This could be simplified by removing the sub-query and just selecting the text from the <v> node where the text of the <k> node matches the search string:
SELECT x.value('(v/text())[1]','varchar(max)') as value
FROM m
CROSS APPLY xml.nodes('//p') as p(x)
WHERE x.value('(k/text())[1]','varchar(max)') = 'Attribute Name 2'
See this demonstrated in this SQL fiddle.
normal practice, i think it's abad practice.sqlserveris a database engine not a parsing engine. Even though, you should look a this question: stackoverflow.com/questions/15680259/parse-xml-in-sql-server