web-dev-qa-db-ja.com

アンパサンドを使用したXMLの解析

XMLを含む文字列があり、それをXelementに解析したいのですが、アンパサンドがあります。 HtmlDecodeでの解析にまだ問題があります。助言がありますか?

string test = " <MyXML><SubXML><XmlEntry Element="test" value="wow&" /></SubXML></MyXML>"; 

XElement.Parse(HttpUtility.HtmlDecode(test));

これらの文字を置き換えるためにこれらのメソッドも追加しましたが、それでもXMLExceptionが発生します。

string encodedXml = test.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;").Replace("\"", "&quot;").Replace("'", "&apos;");
XElement myXML = XElement.Parse(encodedXml);

tまたはこれで試してみました:

string newContent=  SecurityElement.Escape(test);
XElement myXML = XElement.Parse(newContent);
17
paradisonoir

文字列に有効なXMLが含まれていない、それが問題です。文字列を次のように変更する必要があります。

<MyXML><SubXML><XmlEntry Element="test" value="wow&amp;" /></SubXML></MyXML>"
14
Justin Niessner

HtmlEncodeはこのトリックを実行しません。おそらく、さらに多くのアンパサンドを作成します(たとえば、 'は "になります。これは、Xmlエンティティ参照です。

&amp;   & 
&apos;  ' 
&quot;  " 
&lt;    < 
&gt;    > 

ただし、&nbspのようなものが得られる可能性があります。これはhtmlでは問題ありませんが、Xmlでは問題ありません。したがって、他のみんなが言ったように、最初にxmlを修正して、XMLの実際のマークアップの一部ではない(つまり、xml内のすべてのものを変数またはテキスト)、エンティティ参照リストで発生するものは、対応するエンティティに変換されます(したがって、<は<になります)。不正な文字を含むテキストがxmlノード内のテキストである場合は、簡単な方法でテキストをCDATA要素で囲むことができますが、これは属性では機能しません。

3
Colin

文字列が有効なXMLでない場合、解析されません。それ自体にアンパサンドが含まれている場合、それは有効なXMLではありません。 HTMLとは異なり、XMLは非常に厳密です。

0
Tommy Carlier

デコードするのではなく、「エンコード」する必要があります。ただし、HttpUtility.HtmlEncodeを呼び出すと、 '<'および '>'シンボルもエンコードされ、文字列がXMLでなくなるため、役に立ちません。

この場合の最善の解決策は、「&」を「&amp;」に置き換えることだと思います。 (スペースなし)

0
AlexS

おそらく、独自のXMLDocumentScannerを作成することを検討してください。それが、エンティティ参照として使用されていないアンパサンドを無視する機能を持つために NekoHTML が行っていることです。

0

Filip's 答えは正しい方向に進んでいますが、System.Xml.XmlDocumentクラスをハイジャックして、まったく新しいユーティリティ関数なしでこれを行うことができます。

XmlDocument doc = new XmlDocument();
string xmlEscapedString = (doc.CreateTextNode("Unescaped '&' containing string that would have broken your xml")).OuterXml;
0
TheAtomicOption

これは最も単純で最良のアプローチです。すべての文字で機能し、SharePoint ASMXなどのWebサービス呼び出しのXMLを解析できます。

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