Zanim zostaną przeskoczeni przez ludzi mówiąc, że parser XML nie powinien przejmować się, czy elementy są puste czy zamknięte, jest powód, dla którego nie mogę pozwolić na samo-zamknięte elementy XML. Powodem jest to, że faktycznie pracuję z SGML, a nie XML, a DTD SGML, z którym pracuję, jest bardzo surowy i nie pozwala na to.Jak zatrzymać samoczynne zamykanie pustych elementów XML za pomocą XmlDocument w języku C#?
Mam kilka tysięcy plików SGML, które muszę uruchomić na XSLT. Musiałem więc tymczasowo przekonwertować SGML na XML, aby zastosować XSLT. Napisałem następnie metodę, która zamienia je z powrotem na SGML (zasadniczo po prostu zastępując deklarację XML deklaracją SGML i odpisując wszelkie inne deklaracje jednostki, takie jak elementy graficzne).
Mój problem polega na tym, że po tej konwersji z powrotem do SGML, kiedy otwieram pliki w moim edytorze SGML, pliki nie parsują się, ponieważ puste elementy zostały samozamykane.
Czy ktoś wie, jak mogę temu zapobiec, jeśli używasz XmlDocument?
Metody, które przekształcają się SGML do XML iz powrotem są przedstawione poniżej
//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);
}
}
Doskonała i kompleksowa odpowiedź. Dziękuję Ci bardzo. Idealny. –