2012-09-25 30 views
8

मुझे सभी समान स्कीमा/संरचना के बाद हजारों एक्सएमएल फाइलें मिलीं। मैंने IXmlSerializable लागू किया और इस प्रकार तत्वों को पढ़ रहा हूं और खुद को विशेषता देता हूं।.NET एक्सएमएल Deserialization नामस्थानों को अनदेखा

मेरी समस्या यह है कि ये फ़ाइलें प्रत्येक एक अलग फोनी नेमस्पेस का उपयोग करती हैं। ये फ़ाइलें किसी अन्य स्रोत से आती हैं, इसलिए मैं इसे बदल नहीं सकता: डी इसके अलावा, मेरे लिए उन नामस्थानों में से कई हैं जो केवल संभावित नामस्थानों की एक सरणी बनाने और xmlserializer के साथ पास करने के लिए हैं।

अभी, अगर मैं नामस्थान निर्दिष्ट नहीं करता हूं, तो यह एक [xmlns: ns0 = "http://tempuri.org/abcd.xsd" अपेक्षित नहीं था] त्रुटि फेंकता है।

मैं अपने ऑब्जेक्ट को deserializing और केवल ReadXML को आग लगने पर नामस्थान को अनदेखा करने के लिए serializer बताने में सक्षम होना चाहूंगा। या बस इसे "http://tempuri.org/" नामस्थान स्वीकार करने के लिए कहने में सक्षम हो।

क्या यह संभव है?

मैं जितनी ज्यादा हो सके फ़ाइलों को संशोधित करने से बचना चाहता हूं।

धन्यवाद!

+1

क्या आपने नेमस्पेस प्राप्त करने के लिए पहले XML को लोड करने पर विचार किया है ताकि आप उसे XmlSerializer में पास कर सकें? –

+0

@StevenDoggart हां मैंने किया, लेकिन मैं जानना चाहता हूं कि इससे पहले कि मैं इसके आसपास काम करना शुरू करूँ, ऐसा करने के लिए और अधिक "उचित" तरीका है या नहीं। यह सिर्फ मूर्खतापूर्ण लगता है कि आप अपवाद प्राप्त किए बिना नामस्थानों को अनदेखा नहीं कर सकते: एस – user1698428

+0

हां, यह एक बहुत अच्छा सवाल है और अगर इसका उत्तर भी है तो मैं बहुत उत्सुक हूं। –

उत्तर

0

यह आपके प्रश्न का उत्तर नहीं है कि XmlSerialiser को नामस्थानों को अनदेखा करने के लिए कैसे बताना है, लेकिन एक कामकाज। आप xslt ट्रांसफॉर्म का उपयोग कर सकते हैं ताकि इसे क्रमबद्ध करने से पहले xml से नेमस्पेस को पट्टी कर सकें।

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/|comment()|processing-instruction()"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 

इस के लिए सहायकों के रूप में विस्तार के तरीकों में से एक जोड़े, थोड़ा उन सब को शायद पाने के लिए मुश्किल होने जा रहा है, लेकिन मैं कोशिश करता हूँ:

/// <summary> 
/// Transforms the xmldocument to remove all namespaces using xslt 
/// http://stackoverflow.com/questions/987135/how-to-remove-all-namespaces-from-xml-with-c 
/// http://msdn.microsoft.com/en-us/library/42d26t30.aspx 
/// </summary> 
/// <param name="xmlDocument"></param> 
/// <param name="indent"></param> 
public static XmlDocument RemoveXmlNameSpaces(this XmlDocument xmlDocument, bool indent = true) 
{ 
    return xmlDocument.ApplyXsltTransform(Properties.Resources.RemoveNamespaces, indent); 
} 

public static XmlDocument ApplyXsltTransform(this XmlDocument xmlDocument, string xsltString,bool indent= true) 
{ 
    var xslCompiledTransform = new XslCompiledTransform(); 
    Encoding encoding; 
    if (xmlDocument.GetEncoding() == null) 
    { 
     encoding = DefaultEncoding; 
    } 
    else 
    { 
     encoding = Encoding.GetEncoding(xmlDocument.GetXmlDeclaration().Encoding); 
    } 
    using (var xmlTextReader = xsltString.GetXmlTextReader()) 
    { 
     xslCompiledTransform.Load(xmlTextReader); 
    } 
    XPathDocument xPathDocument = null; 
    using (XmlTextReader xmlTextReader = xmlDocument.OuterXml.GetXmlTextReader()) 
    { 
     xPathDocument = new XPathDocument(xmlTextReader); 
    } 
    using (var memoryStream = new MemoryStream()) 
    { 
     using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, new XmlWriterSettings() 
      { 
       Encoding = encoding, 
       Indent = indent 
      })) 
     { 
      xslCompiledTransform.Transform(xPathDocument, xmlWriter); 
     } 
     memoryStream.Position = 0; 
     using (var streamReader = new StreamReader(memoryStream, encoding)) 
     { 
      string readToEnd = streamReader.ReadToEnd(); 
      return readToEnd.ToXmlDocument(); 
     } 
    } 
} 

public static Encoding GetEncoding(this XmlDocument xmlDocument) 
{ 
    XmlDeclaration xmlDeclaration = xmlDocument.GetXmlDeclaration(); 
    if (xmlDeclaration == null) 
     return null; 
    return Encoding.GetEncoding(xmlDeclaration.Encoding); 
} 

public static XmlDeclaration GetXmlDeclaration(this XmlDocument xmlDocument) 
{ 
    XmlDeclaration xmlDeclaration = null; 
    if (xmlDocument.HasChildNodes) 
     xmlDeclaration = xmlDocument.FirstChild as XmlDeclaration; 
    return xmlDeclaration; 
} 

public static XmlTextReader GetXmlTextReader(this string xml) 
{ 
    return new XmlTextReader(new StringReader(xml)); 
} 
0

आप का उपयोग करके xml फ़ाइल से नामस्थान को हटा सकते हैं यह कोड

using (FileStream stream = new FileStream("FilePath",FileMode.Create)) 
       { 
        XmlSerializer serializer = new XmlSerializer(typeof(YourClass)); 
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
        ns.Add("", "");      
        serializer.Serialize(stream," Your Object to Serialize",ns); 
       } 
0

हां, यह संभव है। जब आप अपने XmlSerializer की Deserialize विधि को कॉल करते हैं, तो आप XmlTextReader इंस्टेंस निर्दिष्ट कर सकते हैं।

This answer by Cheeso on a related C# question दिखाता है कि XmlTextReader कैसे बनाएं जो XML फ़ाइल में होने वाली किसी भी नामस्थान को अनदेखा करता है। मैं आपकी आवश्यकताओं के आधार वीबी करने के लिए अपने विचार अनुवाद और एक सरल सबूत अवधारणा-का-उदाहरण बनाने के लिए स्वतंत्रता ले लिया है:

Imports System.IO 
Imports System.Text 
Imports System.Xml 
Imports System.Xml.Serialization 

' Helper class 
Class NamespaceIgnorantXmlTextReader 
    Inherits XmlTextReader 

    Public Sub New(stream As Stream) 
     MyBase.New(stream) 
    End Sub 

    Public Overrides ReadOnly Property NamespaceURI As String 
     Get 
      Return "" 
     End Get 
    End Property 
End Class 

' Serializable class 
Public Class ExampleClass 
    Public Property MyProperty As String 
End Class 

' Example 
Module Module1 
    Sub Main() 
     Dim testXmlStream = New MemoryStream(Encoding.UTF8.GetBytes(
      "<ExampleClass xmlns=""http://tempuri.org/SomePhonyNamespace1.xsd"" 
          xmlns:ph2=""http://tempuri.org/SomePhonyNamespace2.xsd""> 
       <ph2:MyProperty>SomeValue</ph2:MyProperty> 
      </ExampleClass>")) 

     Dim serializer As New XmlSerializer(GetType(ExampleClass)) 
     Dim reader As New NamespaceIgnorantXmlTextReader(testXmlStream) 
     Dim example = DirectCast(serializer.Deserialize(reader), ExampleClass) 

     Console.WriteLine(example.MyProperty) ' prints SomeValue 
    End Sub 
End Module 

नोट: यदि यह सिर्फ दस्तावेज़ के डिफ़ॉल्ट नाम स्थान जो भिन्न है (यानी, अलग-अलग टैगों में अलग-अलग नामस्थान नहीं होते हैं) TextXmlReader का उपयोग Namespaces संपत्ति False पर सेट की गई है।

Imports System.IO 
Imports System.Text 
Imports System.Xml 
Imports System.Xml.Serialization 

' Serializable Class 
Public Class ExampleClass 
    Public Property MyProperty As String 
End Class 

' Example 
Module Module1 
    Sub Main() 
     Dim testXmlStream = New MemoryStream(Encoding.UTF8.GetBytes(
      "<ExampleClass xmlns=""http://tempuri.org/SomePhonyNamespace1.xsd""> 
       <MyProperty>SomeValue</MyProperty> 
      </ExampleClass>")) 

     Dim serializer As New XmlSerializer(GetType(ExampleClass)) 
     Dim reader As New XmlTextReader(testXmlStream) 
     reader.Namespaces = False 
     Dim example = DirectCast(serializer.Deserialize(reader), ExampleClass) 

     Console.WriteLine(example.MyProperty) ' prints SomeValue 
    End Sub 
End Module