11

すべて同じスキーマ/構造に従っている何千もの XML ファイルを取得しました。私は IXmlSerializable を実装したので、要素と属性を自分で読み取っています。

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

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

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

それは可能ですか?

ファイルの変更はできるだけ避けたいと思います。

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

4

4 に答える 4

2

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

関連する C# の質問に関する Cheeso によるこの回答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

注:ドキュメントの既定の名前空間だけが異なる場合 (つまり、個々のタグに異なる名前空間がない場合)、プロパティを に設定した標準TextXmlReaderを使用するだけで十分です。NamespacesFalse

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
于 2016-10-13T21:09:36.477 に答える
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));
}
于 2012-10-11T16:15:02.867 に答える
-1

このコードを使用して、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);
                }
于 2015-02-04T20:03:58.277 に答える