Làm cách nào để ngăn các thuộc tính xmlns trống trong đầu ra từ XmlDocument của .NET?


118

Khi tạo XML từ XmlDocument trong .NET, một xmlnsthuộc tính trống sẽ xuất hiện lần đầu tiên khi một phần tử không có vùng tên liên quan được chèn vào; điều này có thể được ngăn ngừa bằng cách nào?

Thí dụ:

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

Đầu ra:

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

Đầu ra mong muốn :

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

Có giải pháp nào có thể áp dụng cho XmlDocumentmã, không phải điều gì đó xảy ra sau khi chuyển đổi tài liệu thành chuỗi với OuterXmlkhông?

Lý do của tôi để làm điều này là để xem liệu tôi có thể khớp với XML chuẩn của một giao thức cụ thể bằng cách sử dụng XML do XmlDocument tạo hay không. xmlnsThuộc tính trống có thể không làm hỏng hoặc nhầm lẫn trình phân tích cú pháp, nhưng nó cũng không có trong bất kỳ cách sử dụng nào mà tôi đã thấy về giao thức này.

Câu trả lời:


111

Nhờ câu trả lời của Jeremy Lew và một chút nghịch ngợm, tôi đã tìm ra cách loại bỏ các xmlnsthuộc tính trống : chuyển vào không gian tên của nút gốc khi tạo bất kỳ nút con nào mà bạn không muốn có tiền tố. Sử dụng không gian tên không có tiền tố ở gốc có nghĩa là bạn cần phải sử dụng cùng không gian tên đó trên các phần tử con để chúng cũng không có tiền tố.

Mã cố định:

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);

Cảm ơn mọi người vì tất cả câu trả lời của bạn đã dẫn tôi đi đúng hướng!


1
Đúng. Đặt phần tử <loner> trong không gian tên "anything: name-space-1.0" có nghĩa là thuộc tính xmlns trống (không đặt nó trong không gian tên) sẽ không được thêm vào khi nó được tuần tự hóa. Nếu bạn cần làm mới về cách không gian tên hoạt động, hãy xem jclark.com/xml/xmlns.htm
JeniT 26/09/08

2
Chú ý: Các phần tử cần điều này (hoặc có lẽ tốt hơn doc.DocumentElement.NamespaceURI) nhưng không chỉ định không gian tên cho CreateAttribute()bạn, bạn sẽ nhận được xmlns:psomethingngay cả khi nó là cùng một tiểu.
Jason Kleban

87

Đây là một biến thể của câu trả lời của JeniT (Cảm ơn bạn rất nhiều btw!)

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

Điều này giúp loại bỏ việc phải sao chép hoặc lặp lại không gian tên ở mọi nơi.


3
Đáp ứng tốt nhất theo tôi. Chúng ta không cần phải biết không gian tên mặc định của tài liệu là gì (hữu ích khi chúng ta không tạo tệp xml từ đầu, tức là trong các kịch bản đọc và sửa đổi).
MuiBienCarlota

11

Nếu <loner>phần tử trong XML mẫu của bạn không có xmlnskhai báo không gian tên mặc định trên đó, thì phần tử đó sẽ ở trong whatever:name-space-1.0không gian tên thay vì không có trong không gian tên. Nếu đó là những gì bạn muốn, bạn cần tạo phần tử trong không gian tên đó:

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

Nếu bạn muốn <loner>phần tử không có trong không gian tên, thì XML được tạo ra chính là thứ bạn cần và bạn không nên lo lắng về xmlnsthuộc tính được thêm tự động cho bạn.


3
Vấn đề nằm ở trình phân tích cú pháp XML không tuân thủ (thường của Microsoft) không thể đối phó với xmnls = "").
Craig Trader

2
/. gọi là. Họ muốn trả lại nhận xét bashing MS ngẫu nhiên của họ.

@W. Craig Trader - không thể nói rằng tôi đã gặp phải vấn đề đó. Thí dụ?
Kev 25-08

1
Đúng, tôi không muốn nút <loner /> có không gian tên, nhưng tôi cũng không muốn nó có thuộc tính không gian tên trống (xmlns). Lý do của tôi chỉ là xem liệu tôi có thể khớp đầu ra XML của một giao thức cụ thể được thiết lập như thế này hay không.
Neil C. Obremski 25/09/08

5
Đó không phải là sự ném đá ngẫu nhiên. Khối Ứng dụng Trình cập nhật Microsoft sử dụng Tệp kê khai XML để xác định những gì cần cung cấp cho máy khách. Thật không may, trình phân tích cú pháp Manifest không thể đối phó với xmlns = ""; Tôi đã phải viết một trình xử lý hậu kỳ để loại bỏ các thuộc tính xmlns trống.
Craig Trader

7

Vì root nằm trong không gian tên chưa được định sẵn, nên bất kỳ phần tử con nào của root muốn được hủy đặt tên miền phải được xuất như ví dụ của bạn. Giải pháp sẽ là đặt tiền tố gốc như sau:

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

mã:

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);

Cảm ơn, nhưng việc thêm không gian tên vào gốc thực sự sẽ phá vỡ XML của tôi liên quan đến giao thức cụ thể mà tôi đang làm việc.
Neil C. Obremski 25/09/08

Ah! Tôi hiểu rõ hơn những gì bạn đang nói và đã tính đến điều đó khi viết câu trả lời của riêng tôi. Cảm ơn Jeremy
Neil C. Obremski 25/09/08

0

Nếu có thể, hãy tạo một lớp tuần tự hóa rồi thực hiện:

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

Nó an toàn hơn và bạn có thể kiểm soát không gian tên bằng các thuộc tính nếu bạn thực sự cần kiểm soát nhiều hơn.


0

Tôi đã giải quyết vấn đề bằng cách sử dụng Factory Pattern. Tôi đã tạo một nhà máy cho các đối tượng XElement. Là tham số cho việc khởi tạo nhà máy, tôi đã chỉ định một đối tượng XNamespace. Vì vậy, mỗi khi XElement được tạo bởi nhà máy, không gian tên sẽ được thêm tự động. Đây là mã của nhà máy:

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 đã hỏi về XmlDocument, không phải XDocument.
John Saunders

0

Có, bạn có thể ngăn XMLNS khỏi XmlElement. Lần đầu tiên Tạo ra nó đang đến: như thế

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

Thay đổi mã: Và chuyển không gian tên xml như thế này

Mã C #:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.