2010-12-02 35 views
11

Yeni bir XML dosyası oluşturmak için Linq to XML kullanıyorum. Dosyanın bir kısmı var olan bir XML dosyasından aldım. Bunun için aşağıdaki kodu kullanıyorum.XElement bir xmlns ekler

var v2 = new XDocument(
    new XDeclaration("1.0", "utf-16", ""), 
    new XComment(string.Format("Converted from version 1. Date: {0}", DateTime.Now)), 
    new XElement(ns + "keyem", 
    new XAttribute(XNamespace.Xmlns + "xsd", xsd.NamespaceName), 
    new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName), 
    new XAttribute(xsi + "schemaLocation", schemaLocation.NamespaceName), 
    new XAttribute("version", "2"), 
    new XAttribute("description", description), 
    new XElement(ns + "layout", 
     new XAttribute("type", type), 
     new XAttribute("height", height), 
     new XAttribute("width", width), 
     settings.Root)  // XML from an existing file 

Sorun şu ki, varolan dosyadan ilk öğeyi xmlns = "" ekler.

sonucudur:

<?xml version="1.0" encoding="utf-16"?> 
<foo 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://tempuri.org/KeyEmFileSchema.xsd KeyEmFileSchema.xsd" 
    xmlns="http://tempuri.org/KeyEmFileSchema.xsd"> 
    <settings xmlns=""> 
     ... 
    </settings> 
</foo> 

böyle görünüyor gelen okuyorum XML dosyası, ancak

<?xml version="1.0" encoding="utf-16"?> 
<settings> 
    <colormaps> 
    <colormap color="Gray"  textcolor="Black"/> 
    <colormap color="DarkGray" textcolor="White"/> 
    <colormap color="Black" textcolor="White"/> 
    <colormap color="Cyan"  textcolor="Black"/> 
    </colormaps> 
    <macromaps> 
    <macromap pattern="^@([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{ESC}$1{ESC}$2{MOUSERESET}"/> 
    <macromap pattern="^\$([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1{ESC}$2{MOUSERESET}"/> 
    <macromap pattern="^\$([0-9A-F]{2})$"    replace="{USERCLICK}{ESC}$1"/> 
    </macromaps> 
    <keydefault color="Cyan"/> 
    <groupdefault color="DarkGray"/> 
</settings> 

cevap

11

Bu görüyoruz gerekirse bunu değiştirebileceğiniz ayarlar elemanı çünkü (muhtemelen belgenizden geliyor) bu ad alanında yaşamıyor. Varsayılan/null-uri ad alanında yaşıyor.

Ad alanını değiştirmek için giriş belgenizi dönüştürmeniz gerekir. o kadar bulmadan önce

Bu biraz basitleştirilmiş bir örnek ... Bu hedef belgenin buna o xml dosyasındaki her elemanın ad değiştirir, başka bir belgeye xml dosyanızı ve yerleri götürün ama

static void ProcessXmlFile() 
    { 
     XNamespace ns = "http://tempuri.org/KeyEmFileSchema.xsd/"; 

     // load the xml document 
     XElement settings = XElement.Load("data.xml"); 

     // shift ALL elements in the settings document into the target namespace 
     foreach (XElement e in settings.DescendantsAndSelf()) 
     { 
      e.Name = ns + e.Name.LocalName; 
     } 

     // write the output document 
     var file = new XDocument(new XElement(ns + "foo", 
             settings)); 

     Console.Write(file.ToString());    
    } 
Gördüğünüz gibi

sonuç hangi bundan ..., ayarlar eleman foo unsuru olarak aynı ad alanında artık

<foo xmlns="http://tempuri.org/KeyEmFileSchema.xsd/"> 
    <settings> 
    <colormaps> 
     <colormap color="Gray" textcolor="Black" /> 
     <colormap color="DarkGray" textcolor="White" /> 
     <colormap color="Black" textcolor="White" /> 
     <colormap color="Cyan" textcolor="Black" /> 
    </colormaps> 
    <macromaps> 
     <macromap pattern="^@([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{ESC}$1{ESC}$2{MOUSERESET}" /> 
     <macromap pattern="^\$([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1{ESC}$2{MOUSERESET}" /> 
     <macromap pattern="^\$([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1" /> 
    </macromaps> 
    <keydefault color="Cyan" /> 
    <groupdefault color="DarkGray" /> 
    </settings> 
</foo> 

olduğunu. Bu aslında hızlı ve kirli bir xml dönüşümüdür ve içe aktardığınız xml belgesindeki herhangi bir ad alanına açıkça uymaz. Ama bu sizin peşinde olduğunuz şey olabilir veya en azından daha sağlam bir şeyin temelini oluşturabilir.

+0

Bunu anlıyorum, ancak bunu nasıl yaparım? Denedim varsayılanSettings.Name = ns + defaultSettings.Name.LocalName; Ama tüm alt öğeler için yapmalıyım. Daha iyi bir şey olmalı. – magol

+0

Xslt tekniklerini kullanarak belgeyi dönüştürmeniz veya her bir öğeyi okumanız ve kodu dönüştürmeniz gerekir. Temel olarak, yüklediğiniz XDocument bu belgedeki her öğenin ad alanını bilir ve bunun foo ile aynı ad alanı olmadığını bilir. –

+0

Okunduğum xml dosyasını, doğru isim işaretinde olması için değiştirebilir miyim? – magol

1

Bunun için bir uzantı yöntemi yazabilirsiniz. Bu yöntemin bir dönüş değeri vardır, böylece zincirlemeyi destekler, ancak aynı zamanda orijinalin dönüşümünü değiştirir, böylece atama olmadan kullanılabilir.

public static XElement EnsureNamespaceExists(this XElement xElement, XNamespace xNamespace) 
{ 
    string nodeName = xElement.Name.LocalName; 

    if (!xElement.HasAttribute("xmlns")) 
    { 
     foreach (XElement tmpElement in xElement.DescendantsAndSelf()) 
     { 
      tmpElement.Name = xNamespace + tmpElement.Name.LocalName; 
     } 
     xElement = new XElement(xNamespace + nodeName, xElement.FirstNode); 
    } 

    return xElement; 
}