2012-09-25 7 views
8

同じスキーマ/構造の後に何千ものXMLファイルがあります。 私はIXmlSerializableを実装していますので、要素と属性を自分で読み込んでいます。.NET XML逆シリアル化で名前空間が無視される

私の問題は、これらのファイルがそれぞれ異なる偽の名前空間を使用していることです。これらのファイルは他のソースからのものなので、私はそれを変更することはできません:D また、それらの名前空間が多すぎるため、可能な名前空間の配列を作成してxmlserializerに渡してしまいます。

私は名前空間を指定しないと、[xmlns:ns0 = "http://tempuri.org/abcd.xsd" was not expected]というエラーがスローされます。

オブジェクトを逆シリアル化してReadXMLを起動するときにシリアライザに名前空間を無視するように伝えたいと思っています。あるいは、「http://tempuri.org/」名前空間を受け入れるように伝えることができます。

これは可能ですか?

可能な限りファイルを変更しないようにしたいと思います。

ありがとうございました!

+1

XmlSerializerに渡すことができるように名前空間を取得するためにまずXMLを読み込むことを検討しましたか? –

+0

@StevenDoggartはい、私はしましたが、私はそれを回避する前にこれを行うためのより適切な方法があるかどうかを知りたいと思います。例外が発生することなく名前空間を無視できないことはばかげている:S – 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

はい、可能です。 XmlSerializerDeserializeメソッドを呼び出すと、XmlTextReaderインスタンスを指定できます。

This answer by Cheeso on a related C# questionは、XmlTextReaderを作成してXMLファイル内に存在するすべての名前空間を無視する方法を示しています。私はあなたの要件に基づいて、単純な概念実証例をVBに自分のアイデアを翻訳して作成するために自由を取った:

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 

注:それは異なっているだけでドキュメントのデフォルトの名前空間なら(すなわち、個々のタグは異なる名前空間を持たない)TextXmlReaderNamespacesプロパティを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 
関連する問題