2011-02-13 31 views
63

Cómo crear documentos XML con prefijo nodo como:espacios de nombres XElement (¿Cómo?)

<sphinx:docset> 
    <sphinx:schema> 
    <sphinx:field name="subject"/> 
    <sphinx:field name="content"/> 
    <sphinx:attr name="published" type="timestamp"/> 
</sphinx:schema> 

cuando trato de ejecutar algo así como new XElement("sphinx:docset") i conseguir excepción

Excepción no controlada : System.Xml.XmlException: el carácter ':', val hexadecimal ue 0x3A, no se puede incluir en un nombre. en System.Xml.XmlConvert.VerifyNCName (String nombre, ExceptionType exceptionTyp e) en System.Xml.Linq.XName..ctor (ns XNamespace, Cadena localName) en System.Xml.Linq.XNamespace.GetName (String localName) en System.Xml.Linq.XName.Get (String expandedName)

Gracias por la ayuda !;)

+0

Eche un vistazo a la clase 'XmlNamespaceManager'. –

+2

Su documento no es válido. Necesita declarar el prefijo 'sphinx'. –

Respuesta

98

es muy fácil en LINQ para XML:

XNamespace ns = "sphinx"; 
XElement element = new XElement(ns + "docset"); 

O hacer t que "alias" el trabajo correctamente para que se vea como sus ejemplos, algo como esto:

XNamespace ns = "http://url/for/sphinx"; 
XElement element = new XElement("container", 
    new XAttribute(XNamespace.Xmlns + "sphinx", ns), 
    new XElement(ns + "docset", 
     new XElement(ns + "schema"), 
      new XElement(ns + "field", new XAttribute("name", "subject")), 
      new XElement(ns + "field", new XAttribute("name", "content")), 
      new XElement(ns + "attr", 
         new XAttribute("name", "published"), 
         new XAttribute("type", "timestamp")))); 

que produce:

<container xmlns:sphinx="http://url/for/sphinx"> 
    <sphinx:docset> 
    <sphinx:schema /> 
    <sphinx:field name="subject" /> 
    <sphinx:field name="content" /> 
    <sphinx:attr name="published" type="timestamp" /> 
    </sphinx:docset> 
</container> 
+0

gracias, pero para la primera versión obtuve no es lo que quiero;))) – Edward83

+0

@ Edward83: Vea mi otro ejemplo. Básicamente necesitarás el espacio de nombres para ser especificado en xmlns en algún lugar ... –

+0

Después de todos los hacks feos que he usado para hacer esto (métodos estáticos recursivos para adjuntar espacio de nombres a todo) ... intenté este enfoque primero, pero no prefijo XNamespace.Xmlns al espacio de nombres externo. ¿Por qué es ese prefijo incluso necesario? ¿Lo establece para global? – micahhoover

17

Puede leer el espacio de nombre del documento y utilizarlo en consultas como esta :

XDocument xml = XDocument.Load(address); 
XNamespace ns = xml.Root.Name.Namespace; 
foreach (XElement el in xml.Descendants(ns + "whateverYourElementNameIs")) 
    //do stuff 
+0

Buen enfoque (+1)! Sin embargo, esto no funcionó para mí en un caso donde el elemento raíz de XML tenía múltiples atributos xmlns, es decir .: xmlns: soapenv = "..." xmlns = "...". Utilizar xml.Root.GetDefaultNamespace() me consiguió lo que quería, que era el valor del atributo plain xmlns = "...". –