.NET'in XmlDocument'inden çıktıda boş xmlns öznitelikleri nasıl engellenir?


118

.NET'te XmlDocument'ten XML oluştururken xmlns, ilk kez ilişkili bir ad alanı olmayan bir öğe eklendiğinde boş bir öznitelik görünür ; Bu nasıl önlenebilir?

Misal:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root",
    "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner"));
Console.WriteLine(xml.OuterXml);

Çıktı:

<root xmlns="whatever:name-space-1.0"><loner xmlns="" /></root>

İstenilen Çıktı:

<root xmlns="whatever:name-space-1.0"><loner /></root>

Belgeyi bir dizeye dönüştürdükten sonraXmlDocument ortaya çıkan bir şey değil , koda uygulanabilir bir çözüm var mı ?OuterXml

Bunu yapmak için gerekçem, XmlDocument tarafından oluşturulan XML kullanarak belirli bir protokolün standart XML'ini eşleştirip eşleştiremeyeceğimi görmektir. Boş xmlnsnitelik olabilir kırmak veya ayrıştırıcı karıştırmayın, ancak bu protokolün gördüm ayrıca herhangi kullanımında mevcut değil değil.

Yanıtlar:


111

Jeremy Lew cevap ve oyun oynamak yok biraz sayesinde ben boş kaldırmak için nasıl düşündüm xmlnsistediğiniz herhangi bir alt düğüm oluştururken kök düğümün ad geçmek: özelliklerini değil bir önek olması. Kökte önek olmayan bir ad alanını kullanmak, aynı ad alanını alt öğelerde de öneklere sahip olmamak için kullanmanız gerektiği anlamına gelir .

Sabit Kod:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root", "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner", "whatever:name-space-1.0")); 
Console.WriteLine(xml.OuterXml);

Beni doğru yöne götüren tüm cevaplarınız için herkese teşekkürler!


1
Tam. <loner> öğesini "ne olursa olsun: ad-boşluk-1.0" ad alanına koymak, boş xmlns özniteliğinin (bu onu ad alanına koymaz) serileştirildiğinde ona eklenmeyeceği anlamına gelir. Ad
JeniT

2
Dikkat: Öğelerin buna ihtiyacı var (veya belki daha iyisi doc.DocumentElement.NamespaceURI), ancak aynı uri olsa bile CreateAttribute()alacağınız için bir ad alanı belirtmeyin xmlns:psomething.
Jason Kleban

87

Bu, JeniT'nin cevabının bir çeşididir (Çok çok teşekkürler btw!)

XmlElement new_element = doc.CreateElement("Foo", doc.DocumentElement.NamespaceURI);

Bu, ad alanını her yerde kopyalama veya tekrar etme zorunluluğunu ortadan kaldırır.


3
Bana göre en iyi yanıt. Belge varsayılan ad alanının ne olduğunu bilmek zorunda değiliz (sıfırdan bir xml dosyası oluşturmadığımız zaman, yani senaryoları oku ve değiştir).
MuiBienCarlota

11

Eğer <loner>sizin örnek XML elemanı yoktu xmlnsüzerinde varsayılan ad alanı beyanı, o zaman olurdu whatever:name-space-1.0doğrusu hiçbir ad alanında olmaktan çok ad. İstediğiniz buysa, öğeyi o ad alanında oluşturmanız gerekir:

xml.CreateElement("loner", "whatever:name-space-1.0")

<loner>Öğenin herhangi bir ad alanında olmamasını istiyorsanız, üretilen XML tam olarak ihtiyacınız olan şeydir ve sizin xmlnsiçin otomatik olarak eklenen özellik konusunda endişelenmemelisiniz .


3
Sorun, xmnls = "" ile baş edemeyen uyumlu olmayan XML ayrıştırıcılarda (tipik olarak Microsoft'tan) yatmaktadır.
Craig Trader

2
/. aranan. Rastgele MS dayak yorumlarını geri istiyorlar.

@ W. Craig Trader - bununla bir sorunla karşılaştığımı söyleyemem. Misal?
Kev

1
Doğru, <loner /> düğümünün bir ad alanına sahip olmasını istemiyorum, ancak onun da boş bir ad alanı niteliğine (xmlns) sahip olmasını istemiyorum. Benim mantığım, sadece böyle ayarlanmış belirli bir protokolün XML çıktısını eşleştirip eşleştiremeyeceğimi görmektir.
Neil C. Obremski

5
Rastgele dayak değildi. Microsoft Updater Uygulama Bloğu, istemciye ne teslim edileceğini belirlemek için bir XML Bildirimi kullanır. Maalesef, Manifest ayrıştırıcısı xmlns = ""; Boş xmlns özniteliklerini çıkaracak bir son işlemci yazmam gerekiyordu.
Craig Trader

7

Kök öneksiz bir ad alanında olduğundan, ad alanından çıkarılmak isteyen herhangi bir kökün alt öğesi, örneğiniz gibi çıktı alınmalıdır. Çözüm, kök öğenin önekini şu şekilde yapmak olacaktır:

<w:root xmlns:w="whatever:name-space-1.0">
   <loner/>
</w:root>

kod:

XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement( "w", "root", "whatever:name-space-1.0" );
doc.AppendChild( root );
root.AppendChild( doc.CreateElement( "loner" ) );
Console.WriteLine(doc.OuterXml);

Teşekkürler, ancak ad alanını gerçek köke eklemek, üzerinde çalıştığım belirli protokole göre XML'imi bozar.
Neil C. Obremski

Ah! Ne dediğini daha çok anladım ve kendi cevabımı yazarken bunu dikkate aldım. Teşekkürler Jeremy
Neil C. Obremski

0

Mümkünse, bir serileştirme sınıfı oluşturun ve ardından şunları yapın:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(yourType);
serializer.Serialize(xmlTextWriter, someObject, ns);

Daha güvenlidir ve gerçekten daha fazla kontrole ihtiyacınız varsa ad alanlarını niteliklerle kontrol edebilirsiniz.


0

Fabrika Modelini kullanarak sorunu çözdüm. XElement nesneleri için bir fabrika oluşturdum. Fabrikanın somutlaştırılması için parametre olarak bir XNamespace nesnesi belirledim. Bu nedenle, fabrika tarafından her XElement oluşturulduğunda ad alanı otomatik olarak eklenecektir. İşte fabrikanın kodu:

internal class XElementFactory
{
    private readonly XNamespace currentNs;

    public XElementFactory(XNamespace ns)
    {
        this.currentNs = ns;
    }

    internal XElement CreateXElement(String name, params object[] content)
    {
        return new XElement(currentNs + name, content);
    }
}

1
OP soruyordu XmlDocument, değil XDocument.
John Saunders

0

Evet, XMLNS'yi XmlElement'den engelleyebilirsiniz. İlk Yaratma zamanı geliyor: bunun gibi

<trkpt lat="30.53597" lon="-97.753324" xmlns="">
    <ele>249.118774</ele>
    <time>2006-05-05T14:34:44Z</time>
</trkpt>

Kodu değiştirin: Ve xml ad alanını şu şekilde geçirin

C # kodu:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.