Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从序列化值中的Xml节点中删除命名空间属性_C#_Xml_Xmlserializer_Xmldocument_Xmlnode - Fatal编程技术网

C# 从序列化值中的Xml节点中删除命名空间属性

C# 从序列化值中的Xml节点中删除命名空间属性,c#,xml,xmlserializer,xmldocument,xmlnode,C#,Xml,Xmlserializer,Xmldocument,Xmlnode,我必须重新创建供应商的XML文件。我无法访问它们的代码、模式或任何内容,因此我使用XmlSerializer和属性来执行此操作。我这样做是因为系统使用的是一个通用的XmlWriter,我构建它是为了编写其他系统XML文件,所以我一举两得。除了一处房产的价值外,一切都很顺利。供应商XML如下所示: <TextOutlTxt> <p style="text-align:left;margin-top:0pt;margin-bottom:0pt;"> &l

我必须重新创建供应商的XML文件。我无法访问它们的代码、模式或任何内容,因此我使用
XmlSerializer
和属性来执行此操作。我这样做是因为系统使用的是一个通用的
XmlWriter
,我构建它是为了编写其他系统XML文件,所以我一举两得。除了一处房产的价值外,一切都很顺利。供应商XML如下所示:

<TextOutlTxt>
    <p style="text-align:left;margin-top:0pt;margin-bottom:0pt;">
       <span>SUBSTA SF6 CIRCUIT BKR CONC FDN &#x22;C&#x22;</span>
    </p>
</TextOutlTxt>
我肯定我忽略了什么。任何帮助都将不胜感激

更新日期2017年9月26日 所以我被要求提供更多的细节,特别是对代码目的的解释,以及一个可复制的示例。这两个都是:

  • XML的用途。我正在编写两个系统之间的接口UI。我从一个系统中读取数据,给用户提供选择来处理数据,然后让用户能够将数据导出到第二个系统可以导入的文件中。这是一个物料清单系统,其中系统一是CAD图纸和图纸中的对象,系统二是一个企业评估系统,也被配置为支持电子物料清单。供应商给了我XML,让我重新创建
  • 全功能示例代码。。。。我尝试过以可复制的形式概括代码

    [XmlRoot("OutlTxt", Namespace = "http://www.mynamespace/09262017")]
    public class OutlineText
    {
        private string _value;
    
        [XmlElement("TextOutlTxt")]
        public XmlNode Value
        {
            get
            {
                string text = _value;
                text = Regex.Replace(text, @"[\a\b\f\n\r\t\v\\""'&<>]", m => string.Join(string.Empty, m.Value.Select(c => string.Format("&#x{0:X};", Convert.ToInt32(c))).ToArray()));
                string value = "\n<p style=\"text-align:left;margin-top:0pt;margin-bottom:0pt;\">\n<span>ReplaceMe</span>\n</p>\n";
    
                XmlDocument document = new XmlDocument();
                document.InnerXml = "<root>" + value + "</root>";
    
                XmlNode innerNode = document.DocumentElement.FirstChild;
                innerNode.InnerText = text;
    
                return innerNode;
             }
            set
            { }
        }
    
        private OutlineText()
        { }
    
        public OutlineText(string text)
        {
            _value = text;
        }
    
    }
    
     public class XmlFileWriter
    {
        public void Write<T>(T sourceData, FileInfo targetFile) where T : class
        {
            //This is actually retrieved through a locator object, but surely no one will mind an empty
            //collection for the sake of an example
            Type[] knownTypes = new Type[] { };
    
            using (FileStream targetStream = targetFile.OpenWrite())
            {
                 //Let's see if we can get the default namespace
                 XmlRootAttribute xmlRootAttribute = sourceData.GetType().GetCustomAttributes<XmlRootAttribute>().FirstOrDefault();
    
                 XmlSerializer serializer = null;
    
                if (xmlRootAttribute != null)
                {
                     string nameSpace = xmlRootAttribute.Namespace ?? string.Empty;
                     XmlSerializerNamespaces nameSpaces = new XmlSerializerNamespaces();
                     nameSpaces.Add(string.Empty, nameSpace);
                     serializer = new XmlSerializer(typeof(T), new XmlAttributeOverrides(), knownTypes, xmlRootAttribute, nameSpace);
    
                     //Now we can serialize
                    using (StreamWriter writer = new StreamWriter(targetStream))
                    {
                         serializer.Serialize(writer, sourceData, nameSpaces);
                     }
                }
                else
                {
                    serializer = new XmlSerializer(typeof(T), knownTypes);
    
                    //Now we can serialize
                    using (StreamWriter writer = new StreamWriter(targetStream))
                    {
                        serializer.Serialize(writer, sourceData);
                    }
                }
            }
        }
    }
    
    
     public static void Main()
    {
        OutlineText outlineText = new OutlineText(@"SUBSTA SF6 CIRCUIT BKR CONC FDN ""C""");
    
        XmlFileWriter fileWriter = new XmlFileWriter();
        fileWriter.Write<OutlineText>(outlineText, new FileInfo(@"C:\MyDirectory\MyXml.xml"));
    
    
        Console.ReadLine();
    }
    
    我已将示例代码值属性重新排列为:

            private string _value;
    
        [XmlAnyElement("TextOutlTxt", Namespace = "http://www.mynamespace/09262017")]
        public XElement Value
        {
            get
            {
                string value = string.Format("<p xmlns=\"{0}\" style=\"text-align:left;margin-top:0pt;margin-bottom:0pt;\"><span>{1}</span></p>", "http://www.mynamespace/09262017", _value);
    
    
                string innerXml = string.Format("<TextOutlTxt xmlns=\"{0}\">{1}</TextOutlTxt>", "http://www.mynamespace/09262017", value);
    
                XElement element = XElement.Parse(innerXml);
    
                //Remove redundant xmlns attributes
                foreach (XElement descendant in element.DescendantsAndSelf())
                {
                    descendant.Attributes().Where(att => att.IsNamespaceDeclaration && att.Value == "http://www.mynamespace/09262017").Remove();
                }
    
                return element;
            }
            set
            {
                _value = value == null ? null : value.ToString();
            }
        }
    
    但是想要

    SUBSTA SF6 CIRCUIT BKR CONC FDN &#x22;C&#x22;
    

    xmlns=”“
    添加到嵌入XML的原因是您的容器元素
    被声明为在
    中http://www.mynamespace/09262017“
    命名空间,而嵌入的文本XML元素位于空命名空间中。要解决此问题,嵌入的XML文本必须与其父元素位于同一命名空间中

    下面是XML文本。请注意,XML中没有任何声明:

    <p style="text-align:left;margin-top:0pt;margin-bottom:0pt;" xmlns="">SUBSTA SF6 CIRCUIT BKR CONC FDN &amp;#x22;C&amp;#x22;</p>
    
    因此,相应的
    OutlTxt
    根元素将位于
    http://www.mynamespace/09262017
    名称空间。除非重写,否则其所有子元素也将默认为此命名空间。将嵌入的
    XmlNode
    放置在空名称空间中视为覆盖父名称空间,因此需要
    xmlns=“”
    属性

    避免此问题的最简单方法是将嵌入的XML字符串文本自身放置在正确的命名空间中,如下所示:

    <p xmlns="http://www.mynamespace/09262017" style="text-align:left;margin-top:0pt;margin-bottom:0pt;">
    <span>ReplaceMe</span>
    </p>
    
    生成的XML如下所示:

    
    

    SUBSTA SF6电路BKR CONC FDN“C”

    请注意,我已将
    Value
    上的属性从
    [xmlement]
    更改为。我这样做是因为您的
    XML可能在根级别包含多个混合内容节点,例如:

    开始文本中间文本结束文本
    
    使用
    [xmlanyement]
    可以允许返回容器节点,而不会导致额外级别的XML元素嵌套


    示例工作。

    您将
    xmlns=”“
    添加到嵌入式XML的原因是您的容器元素
    声明在
    中。”http://www.mynamespace/09262017“
    命名空间,而嵌入的文本XML元素位于空命名空间中。要解决此问题,嵌入的XML文本必须与其父元素位于同一命名空间中

    下面是XML文本。请注意,XML中没有任何声明:

    <p style="text-align:left;margin-top:0pt;margin-bottom:0pt;" xmlns="">SUBSTA SF6 CIRCUIT BKR CONC FDN &amp;#x22;C&amp;#x22;</p>
    
    因此,相应的
    OutlTxt
    根元素将位于
    http://www.mynamespace/09262017
    名称空间。除非重写,否则其所有子元素也将默认为此命名空间。将嵌入的
    XmlNode
    放置在空名称空间中视为覆盖父名称空间,因此需要
    xmlns=“”
    属性

    避免此问题的最简单方法是将嵌入的XML字符串文本自身放置在正确的命名空间中,如下所示:

    <p xmlns="http://www.mynamespace/09262017" style="text-align:left;margin-top:0pt;margin-bottom:0pt;">
    <span>ReplaceMe</span>
    </p>
    
    生成的XML如下所示:

    
    

    SUBSTA SF6电路BKR CONC FDN“C”

    请注意,我已将
    Value
    上的属性从
    [xmlement]
    更改为。我这样做是因为您的
    XML可能在根级别包含多个混合内容节点,例如:

    开始文本中间文本结束文本
    
    使用
    [xmlanyement]
    可以允许返回容器节点,而不会导致额外级别的XML元素嵌套


    工作示例。

    您的问题现在有两个要求:

  • 序列化时抑制嵌入的
    XElement
    XmlNode
    上的某些
    Xlns=“…”
    属性,以及

  • 强制对元素文本中的某些字符进行转义(例如,
    =>
    ";
    )。尽管XML标准不要求这样做,但您的旧版接收系统显然需要这样做

  • 问题#1可按以下方式解决:

    但是,对于问题2,没有办法强制使用
    XmlNode
    XElement
    对某些字符进行不必要的转义,因为转义是在输出过程中在
    XmlWriter
    级别处理的。而微软的
    XmlWriter
    内置实现似乎没有任何可以强制执行某些字符的功能不需要转义的Acter仍然需要转义。您需要尝试对
    XmlWriter
    XmlTextWriter
    进行子类化(如所述,例如和),然后在写入字符串值时截取字符串值,并根据需要转义引号字符

    因此,作为解决#1和#2的另一种方法,y
     string text = Regex.Replace(element.Value, @"[\a\b\f\n\r\t\v\\""'&<>]", m => string.Join(string.Empty, m.Value.Select(c => string.Format("&#x{0:X};", Convert.ToInt32(c))).ToArray()));
    
    SUBSTA SF6 CIRCUIT BKR CONC FDN &amp;#x22;C&amp;#x22;
    
    SUBSTA SF6 CIRCUIT BKR CONC FDN &#x22;C&#x22;
    
    <p style="text-align:left;margin-top:0pt;margin-bottom:0pt;" xmlns="">SUBSTA SF6 CIRCUIT BKR CONC FDN &amp;#x22;C&amp;#x22;</p>
    
    [XmlRoot("OutlTxt", Namespace = "http://www.mynamespace/09262017")]
    public class OutlineText
    {
    }
    
    <p xmlns="http://www.mynamespace/09262017" style="text-align:left;margin-top:0pt;margin-bottom:0pt;">
    <span>ReplaceMe</span>
    </p>
    
    [XmlRoot("OutlTxt", Namespace = OutlineText.Namespace)]
    public class OutlineText
    {
        public const string Namespace = "http://www.mynamespace/09262017";
    
        private string _value;
    
        [XmlAnyElement("TextOutlTxt", Namespace = OutlineText.Namespace)]
        public XElement Value
        {
            get
            {
                var escapedValue = EscapeTextValue(_value);
    
                var nestedXml = string.Format("<p xmlns=\"{0}\" style=\"text-align:left;margin-top:0pt;margin-bottom:0pt;\"><span>{1}</span></p>", Namespace, escapedValue);
                var outerXml = string.Format("<TextOutlTxt xmlns=\"{0}\">{1}</TextOutlTxt>", Namespace, nestedXml);
    
                var element = XElement.Parse(outerXml);
    
                //Remove redundant xmlns attributes
                element.DescendantsAndSelf().SelectMany(e => e.Attributes()).Where(a => a.IsNamespaceDeclaration && a.Value == Namespace).Remove();
    
                return element;
            }
            set
            {
                _value = value == null ? null : value.Value;
            }
        }
    
        static string EscapeTextValue(string text)
        {
            return Regex.Replace(text, @"[\a\b\f\n\r\t\v\\""'&<>]", m => string.Join(string.Empty, m.Value.Select(c => string.Format("&#x{0:X};", Convert.ToInt32(c))).ToArray()));
        }
    
        private OutlineText()
        { }
    
        public OutlineText(string text)
        {
            _value = text;
        }
    }
    
    [XmlRoot("OutlTxt", Namespace = OutlineText.Namespace)]
    public class OutlineText : IXmlSerializable
    {
        public const string Namespace = "http://www.mynamespace/09262017";
    
        private string _value;
    
        // For debugging purposes.
        internal string InnerValue { get { return _value; } }
    
        static string EscapeTextValue(string text)
        {
            return Regex.Replace(text, @"[\a\b\f\n\r\t\v\\""'&<>]", m => string.Join(string.Empty, m.Value.Select(c => string.Format("&#x{0:X};", Convert.ToInt32(c))).ToArray()));
        }
    
        private OutlineText()
        { }
    
        public OutlineText(string text)
        {
            _value = text;
        }
    
        #region IXmlSerializable Members
    
        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }
    
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            _value = ((XElement)XNode.ReadFrom(reader)).Value;
        }
    
        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            var escapedValue = EscapeTextValue(_value);
            var nestedXml = string.Format("<p style=\"text-align:left;margin-top:0pt;margin-bottom:0pt;\"><span>{0}</span></p>", escapedValue);
            writer.WriteRaw(nestedXml);
        }
    
        #endregion
    }
    
    <OutlTxt xmlns="http://www.mynamespace/09262017"><p style="text-align:left;margin-top:0pt;margin-bottom:0pt;"><span>SUBSTA SF6 CIRCUIT BKR CONC FDN &#x22;C&#x22;</span></p></OutlTxt>