首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在XmlDocument中停止使用C#中的空XML元素自闭?

如何在XmlDocument中停止使用C#中的空XML元素自闭?
EN

Stack Overflow用户
提问于 2017-03-22 18:31:03
回答 1查看 2.1K关注 0票数 7

在我被人们说XML解析器不应该关心元素是空的还是自关闭的之前,我不能允许自关闭的XML元素是有原因的。原因是我实际上使用的是SGML,而不是XML,而且我正在使用的SGML DTD非常严格,不允许使用它。

我所拥有的是几千个SGML文件,我需要在这些文件上运行XSLT。因此,为了应用XSLT,我不得不暂时将SGML转换为XML。然后,我编写了一个将它们转换回SGML的方法(本质上只是将XML声明替换为SGML声明,并将任何其他实体声明(如图形实体)写回去)。

我的问题是,在转换回SGML之后,当我在SGML编辑器中打开文件时,文件不会解析,因为空元素已经自我关闭。

在使用XmlDocument时,有人知道我怎样才能阻止这种情况发生吗?

将SGML转换为XML并再次返回的方法如下所示

代码语言:javascript
复制
//converts the SGML file to XML – it’s during this conversion that the 
//empty elements get self-closed, i think

private XmlDocument convertToXML(TextReader reader)
        {
            // setup SgmlReader
            Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader();
            //sgmlReader.DocType = "HTML";
            sgmlReader.WhitespaceHandling = WhitespaceHandling.All;
            sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower;
            sgmlReader.InputStream = reader;


            // create document
            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;

            doc.XmlResolver = null;
            doc.Load(sgmlReader);
            return doc;
        }

// method to apply the XSLT stylesheet to the XML document

private void filterApplic(string applicFilter)
        {
            string stylesheet = getRequiredStylesheet(); // do this just once

            if (stylesheet != "")
            {
                foreach (string file in FilesToConvert)
                {
                    fileName = Path.GetFileName(file); //gets just the file name from the path
                    fileNameNoExt = Path.GetFileNameWithoutExtension(file);
                    string ext = Path.GetExtension(file);

                    if (ext == ".sgm")
                    {
                        try
                        {
                            publicIdentifier = getDoctype(file); // gets the sgml declaration
                            entitiesList = getEntitites(file); // gets the list of entities

                            TextReader tr = new StreamReader(file);
                            myDoc = convertToXML(tr);

                            myDoc.Save(outputFolder + "\\temp.xml");

                            var myXslTrans = new XslCompiledTransform();

                            myXslTrans.Load(stylesheet);
                            myXslTrans.Transform(outputFolder + "\\temp.xml", Path.Combine(outputFolder, fileNameNoExt +".xml"));

                            XmlDocument convertedDoc = new XmlDocument();
                           convertedDoc.Load(Path.Combine(outputFolder, fileNameNoExt + ".xml"));

                            convertToSGM(convertedDoc);

                            filesTransformed++;
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show(e.ToString());
                        }

                    }
                }
            }
            else
            {
                MessageBox.Show("The stylesheet was retured empty. Cannot perform Applicability filter.");
                return;
            }


            MessageBox.Show("Complete! " + filesTransformed.ToString() + " files filtered for " + applicFilter);
        }


//convert files back to SGML
private void convertToSGM(XmlDocument myDoc)
        {

            using (var stringWriter = new StringWriter())
            using (var xmlTextWriter = XmlWriter.Create(stringWriter, settings))
            {

                myDoc.WriteTo(xmlTextWriter);
                xmlTextWriter.Flush();


                string xmltext = stringWriter.GetStringBuilder().ToString();

                xmltext = xmltext.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "<!DOCTYPE DMODULE " + publicIdentifier + ">");
                xmltext = xmltext.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "<!DOCTYPE DMODULE " + publicIdentifier + ">");

                if (entitiesList.Count != 0)
                {
                    string entityListAsOne = "";

                    foreach (string entity in entitiesList)
                    {
                        entityListAsOne = entityListAsOne + "\r\n" + entity;
                    }

                    xmltext = xmltext.Replace("//EN\">", "//EN\" [" + entityListAsOne + "]>");
                }

                File.WriteAllText(Path.Combine(outputFolder, fileNameNoExt + ".sgm"), xmltext);
            }


        }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-22 19:29:23

一种方法是对适当的XmlWriter进行子类化,并重写WriteEndElement()以调用WriteFullEndElement()

例如,下面是执行此任务的XmlTextWriter的子类版本:

代码语言:javascript
复制
public class FullElementXmlTextWriter : XmlTextWriter
{
    public FullElementXmlTextWriter(TextWriter w) : base(w) { }

    public FullElementXmlTextWriter(Stream w, Encoding encoding) : base(w, encoding) { }

    public FullElementXmlTextWriter(string filename, Encoding encoding) : base(filename, encoding) { }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}

然后像这样使用它:

代码语言:javascript
复制
string xmltext;
using (var stringWriter = new StringWriter())
{
    using (var xmlTextWriter = new FullElementXmlTextWriter(stringWriter))
    {
        myDoc.WriteTo(xmlTextWriter);
    }
    xmltext = stringWriter.ToString();
}

或者,如果您需要XmlWriterSettings提供的控件,您可以使用装饰器模式将任何XmlWriter封装在一个装饰器中,该装饰器自动地将调用从WriteEndElement()映射到WriteFullEndElement()

代码语言:javascript
复制
public class FullElementXmlWriterDecorator : XmlWriterDecorator
{
    public FullElementXmlWriterDecorator(XmlWriter baseWriter) : base(baseWriter) { }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}

public class XmlWriterDecorator : XmlWriter
{
    readonly XmlWriter baseWriter;

    public XmlWriterDecorator(XmlWriter baseWriter)
    {
        if (baseWriter == null)
            throw new ArgumentNullException();
        this.baseWriter = baseWriter;
    }

    protected virtual bool IsSuspended { get { return false; } }

    public override void Close()
    {
        baseWriter.Close();
    }

    public override void Flush()
    {
        baseWriter.Flush();
    }

    public override string LookupPrefix(string ns)
    {
        return baseWriter.LookupPrefix(ns);
    }

    public override void WriteBase64(byte[] buffer, int index, int count)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteBase64(buffer, index, count);
    }

    public override void WriteCData(string text)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteCData(text);
    }

    public override void WriteCharEntity(char ch)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteCharEntity(ch);
    }

    public override void WriteChars(char[] buffer, int index, int count)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteChars(buffer, index, count);
    }

    public override void WriteComment(string text)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteComment(text);
    }

    public override void WriteDocType(string name, string pubid, string sysid, string subset)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteDocType(name, pubid, sysid, subset);
    }

    public override void WriteEndAttribute()
    {
        if (IsSuspended)
            return;
        baseWriter.WriteEndAttribute();
    }

    public override void WriteEndDocument()
    {
        if (IsSuspended)
            return;
        baseWriter.WriteEndDocument();
    }

    public override void WriteEndElement()
    {
        if (IsSuspended)
            return;
        baseWriter.WriteEndElement();
    }

    public override void WriteEntityRef(string name)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteEntityRef(name);
    }

    public override void WriteFullEndElement()
    {
        if (IsSuspended)
            return;
        baseWriter.WriteFullEndElement();
    }

    public override void WriteProcessingInstruction(string name, string text)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteProcessingInstruction(name, text);
    }

    public override void WriteRaw(string data)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteRaw(data);
    }

    public override void WriteRaw(char[] buffer, int index, int count)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteRaw(buffer, index, count);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteStartAttribute(prefix, localName, ns);
    }

    public override void WriteStartDocument(bool standalone)
    {
        baseWriter.WriteStartDocument(standalone);
    }

    public override void WriteStartDocument()
    {
        baseWriter.WriteStartDocument();
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteStartElement(prefix, localName, ns);
    }

    public override WriteState WriteState
    {
        get { return baseWriter.WriteState; }
    }

    public override void WriteString(string text)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteString(text);
    }

    public override void WriteSurrogateCharEntity(char lowChar, char highChar)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteSurrogateCharEntity(lowChar, highChar);
    }

    public override void WriteWhitespace(string ws)
    {
        if (IsSuspended)
            return;
        baseWriter.WriteWhitespace(ws);
    }
}

如果您正在进行异步编写,我相信(但还没有经过测试)您也希望装饰异步方法。

然后像这样使用它:

代码语言:javascript
复制
string xmltext;
using (var stringWriter = new StringWriter())
{
    using (var innerXmlWriter = XmlWriter.Create(stringWriter, settings))
    using (var xmlTextWriter = new FullElementXmlWriterDecorator(innerXmlWriter))
    {
        myDoc.WriteTo(xmlTextWriter);
    }
    xmltext = stringWriter.ToString();
}

小提琴

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42959958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档