簡體   English   中英

使用命名空間處理C#XML反序列化

[英]Handling C# XML Deserialization with Namespaces

我一直在努力反序列化以下XML文檔:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:settings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" mc:Ignorable="w14 w15">
    <w:zoom w:percent="100"></w:zoom>
    <w:proofState w:spelling="clean" w:grammar="clean"></w:proofState>
    <w:defaultTabStop w:val="720"></w:defaultTabStop>
    <w:characterSpacingControl w:val="doNotCompress"></w:characterSpacingControl>
    <w:compat>
        <w:compatSetting w:name="compatibilityMode" w:uri="http://schemas.microsoft.com/office/word" w:val="15"></w:compatSetting>
        <w:compatSetting w:name="overrideTableStyleFontSizeAndJustification" w:uri="http://schemas.microsoft.com/office/word" w:val="1"></w:compatSetting>
        <w:compatSetting w:name="enableOpenTypeFeatures" w:uri="http://schemas.microsoft.com/office/word" w:val="1"></w:compatSetting>
        <w:compatSetting w:name="doNotFlipMirrorIndents" w:uri="http://schemas.microsoft.com/office/word" w:val="1"></w:compatSetting>
        <w:compatSetting w:name="differentiateMultirowTableHeaders" w:uri="http://schemas.microsoft.com/office/word" w:val="1"></w:compatSetting>
    </w:compat>
    <w:rsids>
        <w:rsidRoot w:val="00B31FC7"></w:rsidRoot>
        <w:rsid w:val="00251096"></w:rsid>
        <w:rsid w:val="00481AA7"></w:rsid>
        <w:rsid w:val="005C6856"></w:rsid>
        <w:rsid w:val="00661DE2"></w:rsid>
        <w:rsid w:val="00984D97"></w:rsid>
        <w:rsid w:val="00A06ADC"></w:rsid>
        <w:rsid w:val="00B31FC7"></w:rsid>
    </w:rsids>
    <m:mathPr>
        <m:mathFont m:val="Cambria Math"></m:mathFont>
        <m:brkBin m:val="before"></m:brkBin>
        <m:brkBinSub m:val="--"></m:brkBinSub>
        <m:smallFrac m:val="0"></m:smallFrac>
        <m:dispDef></m:dispDef>
        <m:lMargin m:val="0"></m:lMargin>
        <m:rMargin m:val="0"></m:rMargin>
        <m:defJc m:val="centerGroup"></m:defJc>
        <m:wrapIndent m:val="1440"></m:wrapIndent>
        <m:intLim m:val="subSup"></m:intLim>
        <m:naryLim m:val="undOvr"></m:naryLim>
    </m:mathPr>
    <w:themeFontLang w:val="en-US"></w:themeFontLang>
    <w:clrSchemeMapping w:bg1="light1" w:t1="dark1" w:bg2="light2" w:t2="dark2" w:accent1="accent1" w:accent2="accent2" w:accent3="accent3" w:accent4="accent4" w:accent5="accent5" w:accent6="accent6" w:hyperlink="hyperlink" w:followedHyperlink="followedHyperlink"></w:clrSchemeMapping>
    <w:shapeDefaults>
        <o:shapedefaults v:ext="edit" spidmax="1026"></o:shapedefaults>
        <o:shapelayout v:ext="edit">
            <o:idmap v:ext="edit" data="1"></o:idmap>
        </o:shapelayout>
    </w:shapeDefaults>
    <w:decimalSymbol w:val="."></w:decimalSymbol>
    <w:listSeparator w:val=","></w:listSeparator>
    <w15:chartTrackingRefBased></w15:chartTrackingRefBased>
    <w15:docId w15:val="{23720E07-DD19-46BC-8098-ED32713AB32B}"></w15:docId>
</w:settings>

我只對rsids元素中包含的內容感興趣。 所以我想我可以創建看起來像這樣的類:

 [XmlRoot(ElementName ="settings", Namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main")]
    public class rsids
    {
        [XmlElement(ElementName ="rsids",Namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main")]
        public List<rsid> Rsids { get; set; }
    }

    public class rsid
    {
        [XmlAttribute(Namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main")]
        public static string val { get; set; }
    }

我試圖像這樣反序列化:

XDocument xdoc = XDocument.Load(file);
        using (TextReader reader = new StringReader(xdoc.ToString()))
        {
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(rsids));
                StreamReader sr = new StreamReader(file);
                rsids SettingsXml = (rsids)xmlSerializer.Deserialize(sr);

                foreach (var rsid in SettingsXml.Rsids)
                {
                    Console.WriteLine(rsid.val.Count());
                }

                Console.ReadLine();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadLine();
            }
        }

但是,我收到以下錯誤:“值不能為空”。 這是我第一次嘗試使用命名空間反序列化XML文檔。 我瀏覽了社區,發現很多有類似問題的人的文章,但是在嘗試了一些解決方案后,我就像剛開始並繞圈子時一樣感到困惑。 我想了解這一點。 其中一些已發布的解決方案似乎表明我只需要向裝飾器添加一個空白的Namespace屬性(Namespace =“”),而其他示例則顯示實際的名稱空間uri被引用,但僅用於根元素,而在后續元素\\屬性中保留空白。 我更多地是在尋找關於“為什么”,“何時”使用一種方法而不是另一種方法的教育,以及給出給定XML的如何完成此操作的示例。 感謝您提供的任何幫助。

干杯

距離您不太遠。

  1. 您的XmlElement屬性暗含多個rsids元素。 你想要的是一個單一的rsids包含多個元素rsid元素。 最簡單的方法是使用XmlArrayXmlArrayItem屬性。
  2. val屬性不應為static
  3. 由於XmlSerializer的錯誤 ,您需要在XmlAttribute屬性中包含Form = XmlSchemaForm.Qualified

您還可以省略大多數Namespace屬性,因為它們將被繼承,並且不必顯式指定ElementName

將所有內容放在一起:

[XmlRoot(Namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main")]
public class settings
{
    [XmlArray("rsids")]
    [XmlArrayItem("rsid")]
    public List<rsid> Rsids { get; set; }
}

public class rsid
{
    [XmlAttribute(Form = XmlSchemaForm.Qualified)]
    public string val { get; set; }
}

當然,如果僅此而已,那么簡單的LINQ to XML查詢就會容易得多:

XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

var rsids = doc.Descendants(w + "rsid")
    .Attributes(w + "val")
    .Select(x => x.Value);

有關兩種方法的有效演示,請參見此提琴

嘗試這個

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            int[] rsids = doc.Descendants().Where(x => x.Name.LocalName == "rsids").Select(x => new  {
                rsids = x.Elements().Select(y => int.Parse((string)y.Attribute(x.GetNamespaceOfPrefix("w") + "val"), System.Globalization.NumberStyles.HexNumber))
            }).Select(x => x.rsids).FirstOrDefault().Select(x => x).ToArray();

        }
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM