没有值和架构检查的XML元素

时间:2014-01-31 12:03:02

标签: xml xml-parsing

可能不需要但包含完整性的背景信息

我正在开发一个系统,其中所有用户输入都将存储在xml文件中。目前,用户输入由aspx.net Web表单处理。在后面的C#代码中,我将这些值存储在一个对象中,然后序列化回XML。在显示供用户编辑之前,这些值也会从XML序列化为一个对象。

问题

使用以下架构以XML格式表示数据(我为.Net特定前缀表示道歉)

<?xml version="1.0" encoding="utf-8"?>
  <xsd:schema id="UserInput-Schema"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="urn:UserInput-Schema"
    elementFormDefault="qualified">

     <xsd:element name="userInputData">
       <xsd:complexType>
        <xsd:sequence>

          <xsd:element name="someTextData" type="xsd:string"
            minOccurs="1" maxOccurs="1" />

          <xsd:element name="someOtherTextData" type="xsd:string"
            minOccurs="1" maxOccurs="1" />

          <xsd:element name="yetMoreTextData" type="xsd:string"
            minOccurs="1" maxOccurs="1" />


        </xsd:sequence>
       </xsd:complexType>
     </xsd:element>

  </xsd:schema>

但是,我被告知用户应该能够输入空白值,或者根本不输入值。这实际上不是一个问题,除了当输出不在字段之外时,相应的XML元素在序列化发生后没有值。我正在使用.net XML序列化方法将我的对象转换为XML,这个方法似乎在写出之前对值进行修剪(和XML关键字检查)。

例如:

<?xml version="1.0" encoding="utf-8"?>
  <userInputData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

         <someTextData>I love XML!</someTextData>
         <someOtherTextData/>
         <yetMoreTextData>More text</yetMoreTextData>

  </userInputData>

但是,由于元素缺少值,因此在读回时此XML将无法进行架构验证检查。显然,如果我将minOccurs值更改为可以缺少值的元素(根据新提出的要求,那就是一切),那么上面的XML示例将通过模式验证。

但是,我不喜欢这个想法,因为在非常罕见的情况下,用户 COULD 访问应用程序之外的XML文件并进行编辑。如果用户要完全删除元素(无论它是否具有有效值),那么XML仍将通过模式验证,但对于我们的目的而言无效。

我正在考虑为缺少输入的元素(如“未提供输入”)写出内部识别的值,并将值读取为空字符串(如果找到)。例如,这个:

<?xml version="1.0" encoding="utf-8"?>
  <userInputData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

         <someTextData>I love XML!</someTextData>
         <someOtherTextData>Input not supplied<someOtherTextData>
         <yetMoreTextData>More text</yetMoreTextData>

  </userInputData>

然而,由于XML值必须是人类可读的(ish),因此应该从等式中删除应用程序,否则这已被否决。此外,还为读取器和输出文件增加了不必要的复杂性。我查看了nillable标签(在同事的提示下),但我的研究告诉我,这不是什么可用的。 Nillable(如果我是正确的)用于通知XML解析器,而不允许值为NULL,而不是我们可以为它赋值。

除了将minOccurs值设置为0或写出已知的空白值之外,还有更优雅的方法来处理这种特殊情况吗?

TL;博士

是否可以按以下格式写出没有值的元素:

<someTextValue />

让它仍然通过模式验证而不将minOccurs的值设置为0,或者将其传递给已知的(如“this element is blank”)值?

编辑:

我正在使用的.NET技术来验证模式

算法:

  • 将架构读入架构对象
  • 设置XML Reader设置对象(使用架构)
  • 仔细阅读架构(我们目前尚未解析)
  • 如果有任何错误,ValidationEventHandler
  • 会自动捕获它们

这是我使用的代码块:

private static void ValidateAgainstSchema(Stream schemaToUse, XmlReader documentToValidate)
{
  XmlSchema schema;
  // Ensure that the stream to the schema is read from the very
  // begining of the file.
  schemaToUse.Position = 0;

  // Read the schema from the stream into the XmlSchema object
  using (XmlReader schemaReader = XmlReader.Create(schemaToUse))
  {
    schema = XmlSchema.Read(schemaReader, ValidationEventHandler);
  }

  // Add the schema to a set of schemas
  XmlSchemaSet schemas = new XmlSchemaSet();
  schemas.Add(schema);

  // Set up the schema reader settings
  XmlReaderSettings settings = new XmlReaderSettings();
  settings.ValidationType = ValidationType.Schema;
  settings.Schemas = schemas;
  settings.ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ReportValidationWarnings;
  settings.ValidationEventHandler += ValidationEventHandler;

  // Run through the xml file to be checked, before passing control back
  // to the calling method
  using (var validationReader = XmlReader.Create(documentToValidate, settings))
  {
    while (validationReader.Read())
    {
      // If we fail to read the xml file (badly formed, doesn't match
      // the schema, etc.) then we'll fall through to the event handler
      // (readerSettings_ValidationEventHandler) automatically.
    }
  }
}

private static void ValidationEventHandler(object sender, ValidationEventArgs e)
{
  if (e.Severity == XmlSeverityType.Warning)
  {
    /* warning while parsing XML file */
    // warnings can be ignored for now. These are not critical
  }
  else if (e.Severity == XmlSeverityType.Error)
  {
    /* Error while parsing XML file */
    // Errors are problems with the xml file (when checked against
    // the schema). These are critical issues with the conents of
    // the XML file.
    // Possibly throw an exception?

    throw new Exception(e.Message);
  }
}

0 个答案:

没有答案