XML로 문자열 이스케이프


92

XML 요소의 내용을 채우는 데 사용할 수있는 문자열을 이스케이프 및 이스케이프 해제하는 데 사용할 수있는 C # 함수가 있습니까?

VSTS 2008 + C # + .Net 3.0을 사용하고 있습니다.

편집 1 : 나는 간단하고 짧은 XML 파일을 연결하고 내가 명시 적으로 예를 들어, 내가 둘 필요가 손으로 XML 문자를 이스케이프 할 필요가 그래서, 직렬화를 사용하지 않는 a<b으로 <foo></foo>내가 문자열을 벗어날 필요가 있으므로, a<b및 요소 foo는에 넣어.



15
내가 생각할 수있는 가장 짧은 것 :new XText(unescaped).ToString()
sehe

3
이것에 걸림돌이되는 다른 사람에게는 이것이 최선의 답이라고 생각했습니다. stackoverflow.com/a/5304827/1224069
Philip Pittle

답변:


74
public static string XmlEscape(string unescaped)
{
    XmlDocument doc = new XmlDocument();
    XmlNode node = doc.CreateElement("root");
    node.InnerText = unescaped;
    return node.InnerXml;
}

public static string XmlUnescape(string escaped)
{
    XmlDocument doc = new XmlDocument();
    XmlNode node = doc.CreateElement("root");
    node.InnerXml = escaped;
    return node.InnerText;
}

5
문서에 요소를 추가 할 필요도 없습니다. 그러나 나는 아직도 그것의 가장 처음에이 일을하려고하지 말 것 - 조지 ... 손으로 일을 수행하여 자신을위한 일을하고있다처럼 소리
존 소총

15
이 답변은 너무 무겁기 때문에 정말 싫어합니다. XmlDocument는 XmlReader / XmlWriter를 사용하여 실제 작업을 수행 할 것입니다. 따라서 추적을 중단하고 무거운 DOM을 피하는 것은 어떻습니까?
Steven Sudit

7
@Will, OP는 속성이 아닌 XML 요소에 넣을 수있는 텍스트를 이스케이프하는 함수를 요청했습니다 . 내 함수는 작은 따옴표 나 큰 따옴표를 XML 요소에 넣을 수 있기 때문에 이스케이프하지 않습니다.
Darin Dimitrov

5
@darin 좋은 점, 그리고 강조해야 할 점. 이 대화의 결과에 만족하며 예약을 철회합니다. 좋은 하루 되세요.

1
HttpUtility.HtmlEncodefrom System.Web을 안전하게 사용할 수 있는지 궁금합니다 .
Pooven

127

9
이 답변은 선택한 답변과 달리 따옴표를 이스케이프합니다.

2
이 답변은 와 같은 유효하지 않은 문자에서 작동하지 않는 것 같습니다.
Haacked

16
그리고 어떻게 탈출을 해제합니까?
Gondy

2
이 답변은 불완전합니다. 질문의 절반 만 대답합니다.
Brian Webster

1
위의 의견에 동의합니다. 불완전하고 100 % 정확하지 않습니다.
G. Stoynev 2013

38

편집 : "간단하고 짧은 XML 파일을 연결하고 있으며 직렬화를 사용하지 않으므로 명시 적으로 XML 문자를 직접 이스케이프해야합니다."라고 말합니다.

손으로하지 말 것을 강력히 권합니다. XML API를 사용하여 모든 작업을 수행하십시오. 원본 파일을 읽고 필요에 따라 두 문서를 단일 문서로 병합 한 다음 (를 사용하고 싶을 것입니다 XmlDocument.ImportNode) 다시 작성하십시오. 자신 만의 XML 파서 / 포매터를 작성하고 싶지 않습니다. 여기서 직렬화는 다소 관련이 없습니다.

당신이하려는 일에 대한 짧지 만 완전한 예를 우리에게 줄 수 있다면, 우리는 아마 당신이 애초에 탈출에 대해 걱정할 필요가 없도록 도울 수있을 것입니다.


원래 답변

의미하는 바가 완전히 명확하지는 않지만 일반적으로 XML API가이를 수행합니다. 노드에 텍스트를 설정하면 필요한 모든 것을 자동으로 이스케이프 처리합니다. 예를 들면 :

LINQ to XML 예제 :

using System;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        XElement element = new XElement("tag",
                                        "Brackets & stuff <>");

        Console.WriteLine(element);
    }
}

DOM 예 :

using System;
using System.Xml;

class Test
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        XmlElement element = doc.CreateElement("tag");
        element.InnerText = "Brackets & stuff <>";
        Console.WriteLine(element.OuterXml);
    }
}

두 예의 출력 :

<tag>Brackets &amp; stuff &lt;&gt;</tag>

물론 XML 이스케이프를 원한다고 가정합니다. 그렇지 않은 경우 자세한 내용을 게시하십시오.


Jon에게 감사합니다. 원본 게시물 EDIT 1 섹션에 자세한 내용을 추가했습니다. 저에게 몇 가지 의견과 조언을 해주시면 감사하겠습니다. :-)
George2

"XML 이스케이프 이후"-의미합니까? 다른 말로 말씀해 주시겠습니까? 영어는 제 모국어가 아닙니다. :-)
George2

안녕하세요 Jon, XML 형식에서 일반 문자열 형식으로 이스케이프를 해제하는 방법, 즉 입력 "Brackets & amp; stuff & lt; & gt;"에서 "Brackets & stuff <>"출력을 얻습니까?
George2

2
@ George2 : XElement에 값을 요청하거나 XmlElement에 InnerText를 요청합니다.
Jon Skeet

25

한 줄 이스케이프에 대해 @sehe에게 감사드립니다.

var escaped = new System.Xml.Linq.XText(unescaped).ToString();

여기에 한 줄 탈출 해제를 추가합니다.

var unescapedAgain = System.Xml.XmlReader.Create(new StringReader("<r>" + escaped + "</r>")).ReadElementString();

XText는 따옴표를 이스케이프하지 않습니다.
머트 Gülsoy

9

조지, 간단합니다. 항상 XML API를 사용하여 XML을 처리하십시오. 그들은 당신을 위해 모든 탈출 및 탈출을 수행합니다.

문자열을 추가하여 XML을 만들지 마십시오.


살아가는 말. 사용 가능한 많은 XML API 옵션이 있지만 우리 모두가 동의해야하는 한 가지는 수동 문자열 연결이 허용되지 않는다는 것입니다.
Steven Sudit

일반적으로 이에 동의하지만 수동 이스케이프가 필요한 매우 드문 경우가있을 수 있습니다. 예를 들어 Roslyn을 사용하여 XML 문서를 만드는 동안.
svick

@svick : LINQ to XML을 사용하여 XML을 만든 다음 .ToString ()을 사용하지 않는 이유는 무엇입니까?
John Saunders

@JohnSaunders, Roslyn에는 XmlElementSyntax. 또한 생성해야한다는 사실로 인해 복잡합니다 ///. 그리고 여러 줄 XObject태그에 대해 작동하지 않기 때문에 각 줄을 별도의으로 생성 할 수 없습니다 .
svick

1
@svick : XML을 모두 한 줄에 생성하고 그 앞에 붙인 ///다음 코드를 다시 포맷하십시오. 큰 문제는 아니며 확실히 코너 케이스입니다. 꼭 필요한 경우 XmlWriter원하는 방식으로 줄 바꿈 및 공백을 수행 하는 사용자 지정 을 만들 수 있지만 ///새 줄 앞에 배치 할 수 있습니다. 또는 XSLT를 사용하여 XML을 예쁘게 인쇄합니다. 그러나 어쨌든 XML은 여전히 ​​XML API에 의해 생성되어야합니다.
John Saunders

6

예를 들어 XML 직렬화에서 읽을 때와 같이이 질문을 찾았을 때 저처럼 XML 노드 이름을 이스케이프하려면 가장 쉬운 방법을 사용하십시오.

XmlConvert.EncodeName(string nameToEscape)

또한 XML 요소에 대해 공백과 유효하지 않은 문자를 이스케이프합니다.

http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape%28VS.80%29.aspx


질문에 따르면 그들은 단지 내부 텍스트를 원한다고 생각합니다. 귀하의 솔루션은 작동하지만 다소 과잉 또한 요소와 속성 이름 같은 것들을 처리하기위한 것 같다 것입니다. \
숀 더간

1
나는 노드 이름을 벗어나려고 여기에 왔고 내 발견이 미래에 누구에게나 도움이 될 것이라고 생각했습니다. 나는 또한 "과잉"이 무엇인지 보지 않지만 괜찮습니다. ;)
CharlieBrown 2014 년

오, 유용한 정보입니다. :) 나는 당신이 찬성하지 않은 이유 중 하나가 사람들이 당신이 당면한 질문에 대답하지 않는다고 느낄 수도 있기 때문이라고 지적했습니다.
Sean Duggan 2014 년

링크는 SecurityElement.Escape (String)에 대한 문서로 연결됩니다. XmlConvert.EncodeName (String)에는 자체 페이지가 있습니다. 이 질문을받은 지 몇 년이 지났다는 것을 알고 있지만 어떤 것을 사용해야하는지 어떻게 알 수 있습니까? 그들은 같은 일을하지 않고 다른 방식으로 수행합니까?
micnil

@CharlieBrown : 아마도 당신은 그것으로부터 별도의 질문을 만들어서 사람들이 더 잘 찾을 수 있도록 대답하고 싶을 것입니다. 게시 해 주셔서 감사합니다!
Florian Straub

5

태그를 반환하지 않는 John Skeet의 답변을 기반으로 한 또 다른 테이크 :

void Main()
{
    XmlString("Brackets & stuff <> and \"quotes\"").Dump();
}

public string XmlString(string text)
{
    return new XElement("t", text).LastNode.ToString();
} 

그러면 전달 된 값만 XML 인코딩 형식으로 반환됩니다.

Brackets &amp; stuff &lt;&gt; and "quotes"

4

경고 : 네크 로맨싱

여전히 Darin Dimitrov의 답변 + System.Security.SecurityElement.Escape (string s)가 완료되지 않았습니다.

XML 1.1에서 가장 간단하고 안전한 방법은 모든 것을 인코딩하는 것입니다. \ t
처럼 &#09;.
XML 1.0에서는 전혀 지원되지 않습니다.
XML 1.0의 경우 가능한 해결 방법 중 하나는 문자가 포함 된 텍스트를 base-64로 인코딩하는 것입니다.

//string EncodedXml = SpecialXmlEscape("привет мир");
//Console.WriteLine(EncodedXml);
//string DecodedXml = XmlUnescape(EncodedXml);
//Console.WriteLine(DecodedXml);
public static string SpecialXmlEscape(string input)
{
    //string content = System.Xml.XmlConvert.EncodeName("\t");
    //string content = System.Security.SecurityElement.Escape("\t");
    //string strDelimiter = System.Web.HttpUtility.HtmlEncode("\t"); // XmlEscape("\t"); //XmlDecode("&#09;");
    //strDelimiter = XmlUnescape("&#59;");
    //Console.WriteLine(strDelimiter);
    //Console.WriteLine(string.Format("&#{0};", (int)';'));
    //Console.WriteLine(System.Text.Encoding.ASCII.HeaderName);
    //Console.WriteLine(System.Text.Encoding.UTF8.HeaderName);


    string strXmlText = "";

    if (string.IsNullOrEmpty(input))
        return input;


    System.Text.StringBuilder sb = new StringBuilder();

    for (int i = 0; i < input.Length; ++i)
    {
        sb.AppendFormat("&#{0};", (int)input[i]);
    }

    strXmlText = sb.ToString();
    sb.Clear();
    sb = null;

    return strXmlText;
} // End Function SpecialXmlEscape

XML 1.0 :

public static string Base64Encode(string plainText)
{
    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
    return System.Convert.ToBase64String(plainTextBytes);
}

public static string Base64Decode(string base64EncodedData)
{
    var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
    return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}

그렇다면 XML 1.1에서 모든 것을 어떻게 이스케이프합니까?
Philip Pittle 2015 년

@Philip Pittle : SpecialXmlEscape 참조
Stefan Steiger

3

다음 기능이 작동합니다. XmlDocument에 대해 테스트하지 않았지만 이것이 훨씬 빠르다고 생각합니다.

public static string XmlEncode(string value)
{
    System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings 
    {
        ConformanceLevel = System.Xml.ConformanceLevel.Fragment
    };

    StringBuilder builder = new StringBuilder();

    using (var writer = System.Xml.XmlWriter.Create(builder, settings))
    {
        writer.WriteString(value);
    }

    return builder.ToString();
}

public static string XmlDecode(string xmlEncodedValue)
{
    System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings
    {
        ConformanceLevel = System.Xml.ConformanceLevel.Fragment
    };

    using (var stringReader = new System.IO.StringReader(xmlEncodedValue))
    {
        using (var xmlReader = System.Xml.XmlReader.Create(stringReader, settings))
        {
            xmlReader.Read();
            return xmlReader.Value;
        }
    }
}

3

타사 라이브러리 ( Newtonsoft.Json )를 대안으로 사용 :

public static string XmlEncode(string unescaped)
{
    if (unescaped == null) return null;
    return JsonConvert.SerializeObject(unescaped); ;
}

public static string XmlDecode(string escaped)
{
    if (escaped == null) return null;
    return JsonConvert.DeserializeObject(escaped, typeof(string)).ToString();
}

예:

a<b <==> "a&lt;b"

<foo></foo> <==> "foo&gt;&lt;/foo&gt;"

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.