2011-11-29 27 views
5

Tengo un servicio web que devuelve una cadena xml como resultados. La cadena devuelta está en este formato:Incrustar un documento xml dentro de una cadena xml

<ReturnValue> 
    <ErrorNumber>0 
</ErrorNumber> 
<Message>my message</Message> 
</ReturnValue> 

Los datos que quiero insertar en la etiqueta de "mensaje" es una versión serializada de un objeto personalizado. El formato serializado de ese objeto contiene xml y las publicaciones del espacio de nombres publican la serialización. Cuando eso se agrega a la etiqueta "mensaje" de mi cadena xml de retorno, XmlSpy dice que no está bien formado. ¿Cómo debo deshacerme de las declaraciones del espacio de nombres, o hay una forma diferente de insertar un objeto serializado en una cadena xml?

+0

declaraciones de espacios de nombres redundantes o nuevos en los datos incrustados no deben causar errores de buena formación, pero también la incorporación de la declaración XML dentro de su elemento '' probablemente causarán eso. Si eliminar la declaración XML adicional no soluciona el problema, entonces la serialización de los objetos o el valor de retorno del servicio web producen XML mal formado. – jasso

Respuesta

6

Sólo asegúrese de que su <Message> XML está codificado de manera que <, >, " y & aparecen como &lt;, &gt;, y &quot;&amp;, respectivamente.

hay pocos incorporada maneras de codificar los caracteres:

string message = System.Web.HttpUtility.HtmlEncode(serializedXml); 

string message = System.Security.SecurityElement.Escape(serializedXml); 
  • El uso de un XmlTextWriter para hacer el trabajo para usted
  • Uso CDATA para envolver el código XML

también , este es probablemente un duplicado de:

  1. Best way to encode text data for XML
+0

¿Sería tan fácil como hacer una cadena. Reemplazar todas las representaciones diferentes de esos caracteres especiales xml? – ganders

6

Envuelva la cadena en CDATA así:

<![CDATA[your xml, which can be multi-line]]> 

CDATA informará a un validador para tratar el contenido CDATA como texto ignorado. A menudo es la forma más conveniente de incrustar XML (o contenido tagging no XML) como una cadena. Puede tener problemas si su XML incrustado contiene su propio CDATA, pero de lo contrario es una solución simple.

+0

(googleando CDATA ...) – ganders

0

Piense en XML como un documento, no como una cadena. Crea un nodo llamado "envoltorio" y almacena el contenido de tu archivo en él como una cadena codificada en Base64. Los resultados se verán así.

<ReturnValue> 
    <ErrorNumber>0</ErrorNumber> 
    <Message>my message</Message> 
    <wrapper type="bin.base64">PD94bWwgdmVyc2lvbj0iMS4wIj8+PHhzbDpzdHlsZXNoZWV0IHZ 
lcnNpb249IjEuMCIgeG1sbnM6eHNsPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L1hTTC9UcmFuc2Zvcm0 
iIHhtbG5zOm1zeHNsPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnhzbHQiPjx4c2w6b3V0cHV0IG1 
ldGhvZD0ieG1sIiAvPjx4c2w6dGVtcGxhdGUgbWF0Y2g9Ii8iPjwveHNsOnRlbXBsYXRlPjwveHNsOnN 
0eWxlc2hlZXQ+</wrapper> 
</ReturnValue> 

El siguiente código muestra cómo agregar el contenedor, codificar el contenido. Luego invierte el proceso para mostrar que todo "funciona".

El uso de Base64 en XML también tiene otras aplicaciones. Por ejemplo, incrustación de imágenes u otros documentos en contenido XML.

using System; 
using System.IO; 
using System.Xml; 

public class t 
{ 

    static public string EncodeTo64(string toEncode) { 
     byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); 
     string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); 
     return returnValue; 
    } 

    static public string DecodeFrom64(string encodedData) { 
     byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData); 
     string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes); 
     return returnValue; 
    } 

    public static void Main() { 
     try { 
     //Create the XmlDocument. 
     XmlDocument doc = new XmlDocument(); 
      doc.LoadXml(@" 
      <ReturnValue> 
      <ErrorNumber>0</ErrorNumber> 
      <Message>my message</Message> 
      </ReturnValue> 
      "); 

      XmlNode nodeMessage = doc.SelectSingleNode("/ReturnValue/Message"); 
      if(nodeMessage != null) { 
      XmlDocument docImport = new XmlDocument(); 
       docImport.Load("docwithnamespace.xml"); 

       // create a wrapper element for the file, then import and append it after <Message> 
       XmlElement nodeWrapper = (XmlElement)doc.CreateElement("wrapper"); 
       nodeWrapper.SetAttribute("type", "bin.base64"); 

       nodeWrapper = (XmlElement)doc.ImportNode(nodeWrapper, true); 
       XmlNode ndImport = nodeMessage.ParentNode.AppendChild(nodeWrapper.CloneNode(true)); 
       ndImport.InnerText = EncodeTo64(docImport.OuterXml); 
       doc.Save("wrapperadded.xml"); 

       // Next, let's test un-doing the wrapping 
       // Re-load the "wrapped" document 
       XmlDocument docSaved = new XmlDocument(); 
       docSaved.Load("wrapperadded.xml"); 

       // Get the wrapped element, decode from base64 write to disk 
       XmlNode node = doc.SelectSingleNode("/ReturnValue/wrapper"); 
       if(node != null) { 
        // Load the content, and save as a new XML 
        XmlDocument docUnwrapped = new XmlDocument(); 
        docUnwrapped.LoadXml(DecodeFrom64(node.InnerText)); 
        docUnwrapped.Save("unwrapped.xml"); 
        Console.WriteLine("Eureka"); 
       } 
      } 


     } catch(Exception e) { 
      Console.WriteLine(e.Message); 
     } 
    } 
} 
Cuestiones relacionadas