Pregunta

Estoy trabajando con algunos fragmentos xml '' que forman los elementos abajo el código XML. Tengo el esquema pero no puedo validar estos archivos porque no son documentos XML completos. Estos fragmentos se envuelven con los elementos principales necesarios para formar XML válido cuando se utilizan en otras herramientas, así que no tengo mucha opción de convertirlos en XML válido o en el cambio del esquema.

¿Es posible validar un elemento, en lugar de todo el documento? Si no, ¿qué soluciones podrían sugerirse?

Estoy trabajando en C # con .NET 2.0 Framework.

¿Fue útil?

Solución

He tenido un problema similar en el que sólo podía validar partes de mi documento XML. Se me ocurrió con este método aquí:

private void ValidateSubnode(XmlNode node, XmlSchema schema)
{
    XmlTextReader reader = new XmlTextReader(node.OuterXml, XmlNodeType.Element, null);

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ConformanceLevel = ConformanceLevel.Fragment;
    settings.Schemas.Add(schema);
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationEventHandler += new ValidationEventHandler(XSDValidationEventHandler);

    using (XmlReader validationReader = XmlReader.Create(reader, settings))
    {     
        while (validationReader.Read())
        {
        }
    }
}

private void XSDValidationEventHandler(object sender, ValidationEventArgs args)
{
    errors.AppendFormat("XSD - Severity {0} - {1}", 
                        args.Severity.ToString(), args.Message);
}

Básicamente, lo paso un XmlNode (que selecciono de todo el XmlDocument por medio de .SelectSingleNode), y un esquema XML, que me carga de un XSD recurso incrustado dentro de mi aplicación. Cualquier error de validación que pudieran ocurrir se están metidos en una "errores" constructor de cadena, que luego leí al final, para ver si hubo algún error registrados, o no.

funciona para mí - su experiencia puede variar: -)

Otros consejos

Hay un método XmlDocument.Validate que toma un XmlNode como argumento una valida solamente este nodo. Eso puede ser lo que estás buscando ...

Ok, aquí hay otro enfoque:

Se puede transformar el archivo de esquema por medio de una transformación XSLT en un nuevo esquema que tiene sus elementos como fragmento de raíz. Digamos que su esquema original sería

<xs:schema id="MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="RootElement">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="NestedElement">
          <xs:complexType>
            <xs:attribute name="Name" type="xs:string" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Hay fragmentos de tipo NestedElement que desee validar:

<NestedElement Name1="Name1" />

A continuación, se puede utilizar como una plantilla XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="xs:element[@name='NestedElement']"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:schema id="MySchema">
      <xsl:copy-of select="."/>
    </xs:schema>
  </xsl:template>
</xsl:stylesheet>

Para crear un nuevo esquema que ha NestedElement como root. El esquema resultante se vería

<xs:schema id="MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="NestedElement">
    <xs:complexType>
      <xs:attribute name="Name" type="xs:string" use="required" />
    </xs:complexType>
  </xs:element>
</xs:schema>

A continuación, puede validar un documento fragmento en contra de este nuevo esquema utilizando un código como

XmlSchema schema;
using (MemoryStream stream =    new MemoryStream())
using (FileStream fs = new FileStream("MySchema.xsd", FileMode.Open))
using(XmlReader reader = XmlReader.Create(fs)) {
  XslCompiledTransform transform = new XslCompiledTransform();
  transform.Load("SchemaTransform.xslt");
  transform.Transform(reader, null, stream);
  stream.Seek(0, SeekOrigin.Begin);
  schema = XmlSchema.Read(stream, null);
}
XmlDocument doc = new XmlDocument();
doc.Schemas.Add(schema);
doc.Load("rootelement.xml");
doc.Validate(ValidationHandler);

MySchema.xsd es el esquema original, SchemaTransform.xslt es la transformación (como se muestra más arriba), rootelement.xml es un documento XML que contiene un único nodo fragmento.

Puede utilizar un alias de espacio de nombres especial a destinar los elementos que desea validar y sólo añadir esquema para ese alias espacio de nombres, pero no para otros. De esta manera sólo los elementos con el prefijo de espacio de nombres especial conseguirán validado.

No no parece posible hacer lo que aspiro a hacer. Mi trabajo actual es alrededor para crear un documento XML plantilla en blanco. A continuación, reemplace el elemento deseado con mi fragmento. A partir de ahí, creo que el método Validar entonces sería viable. Pero para crear esta plantilla dinámica parece ser otra tarea de enormes proporciones en su propio derecho. No parece haber ninguna manera fácil de crear un documento 'esqueleto'.

Yo tenía el mismo problema. Incluso se le preguntó aquí para la solución. He encontrado una solución.

El problema es que sólo los elementos raíz se pueden validar. Así que ... edito el esquema en la memoria y añadir el elemento / tipo para validar a la raíz

public static void AddElementToSchema(XmlSchema xmlSchema, string elementName, string elementType, string xmlNamespace)
{
    XmlSchemaElement testNode = new XmlSchemaElement();
    testNode.Name = elementName;
    testNode.Namespaces.Add("", xmlNamespace);
    testNode.SchemaTypeName = new XmlQualifiedName(elementType, xmlNamespace);
    xmlSchema.Items.Add(testNode);
    xmlSchema.Compile(XMLValidationEventHandler);
}

Sólo un par de líneas y que no debe modificar o añadir cualquier archivo XSD :) Con este simple cambio en su esquema en memoria, puede validar el fragmento con el mismo código que se utiliza para validar un documento completo. Sólo asegúrese de que el elemento raíz del fragmento para validar incluye el espacio de nombres. :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top