Не могу проверить простой (или сложный) XML с DTD, используя c # и vs2017 - PullRequest
0 голосов
/ 21 февраля 2019

Я работал над проблемой, пытаясь проверить XML-документ со связанным файлом DTD.Сначала я попытался преобразовать пример из ( Micorsoft Article ), а затем прочитал статью в другой статье Stack-Overflow ( здесь ).В обоих случаях (действительные и недействительные документы XML) простой xml-файл не проходит проверку, и я не могу понять, почему ...

Мое тестовое приложение - это проект Windows Forms с одной формой, в которой есть паракнопок на нем, и следующий код за ним ...

bool isValid = true;
    StringBuilder xml = new StringBuilder();
    StringBuilder messages = new StringBuilder();
    string nl = Environment.NewLine;

    public FormMain()
    {
        InitializeComponent();
    }

    private void ValidateProductXMLButton_Click(object sender, EventArgs e)
    {
        ValidateXML("ProductWithDTD.xml");
        DisplayMessage();
    }

    private void ValidateItemXMLButton_Click(object sender, EventArgs e)
    {
        ValidateXML("ItemWithDTD.xml");
        DisplayMessage();
    }

    private void DisplayMessage()
    {
        MessageBox.Show("XML is " + (isValid ? "" : "NOT ") + "valid" + nl + nl + "Message:" + nl + messages.ToString() + nl + nl + "XML" + nl + xml.ToString());

        isValid = true;
        messages = new StringBuilder();
        xml = new StringBuilder();
    }

    protected void ValidateXML(string xmlFileName)
    {
        try
        {
            XmlReaderSettings xmlSettings = new XmlReaderSettings()
            {   
                DtdProcessing = DtdProcessing.Parse,
                ValidationType = ValidationType.DTD
            };
            xmlSettings.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);

            XmlReader reader = XmlReader.Create(AppDomain.CurrentDomain.BaseDirectory + xmlFileName, xmlSettings);
            while (reader.Read())
            {
                // nothing to do, just validating the xml packet
                xml.AppendLine(reader.ReadOuterXml());
            }
            reader.Close();
        }
        catch (Exception ex)
        {
            messages.AppendLine("ERROR : " + ex.Message);
            isValid = false;
        }
    }

    private void ValidationCallback(object sender, ValidationEventArgs e)
    {
        isValid = false;
        messages.AppendLine(e.Message);
    }

В дополнение к приведенному выше коду показаны содержимое моих двух файлов XML (один действительный, а другой нет) и мой файл DTD.ниже ...

ProductWithDTD.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE Product SYSTEM "Product.dtd">
<Product ProductID="123">
    <ProductName>Rugby jersey</ProductName>
</Product>

ItemWithDTD.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE Product SYSTEM "Product.dtd">
<Item ItemID="123">
    <ItemName>Rugby jersey</ItemName>
</Item>

и, наконец, Product.dtd ...

<!ELEMENT Product (ProductName)>
<!ATTLIST Product ProductID CDATA #REQUIRED>
<!ELEMENT ProductName (#PCDATA)>

Даже при обработке файла ProductWithDTD.xml я получаю ошибки проверки, указывающие, что элементы Product и ProductName не объявлены.Я ожидал бы этого в файле ItemWithDTD.xml, но не в файле ProductWithDTD.xml.

У кого-нибудь есть идеи, почему это не удается?Все это готовится к проверке пакетов EDI cXML (которые также не работают), и они являются гораздо большими документами для проверки.

Спасибо.

1 Ответ

0 голосов
/ 18 марта 2019

Оказывается, что проблема в том, что XmlReader фактически находит файл DTD для проверки, даже если это локальный файл.

Изменение определения XmlReaderSettings для включения в него значения по умолчанию XmlResolver устранило мою проблему.

            XmlReaderSettings xmlSettings = new XmlReaderSettings()
            {   
                DtdProcessing = DtdProcessing.Parse,
                ValidationType = ValidationType.DTD,
                XmlResolver = new XmlUrlResolver()
            };
...