Domanda

Sto lavorando con alcuni XML 'frammenti' che costituiscono gli elementi lungo il xml. Ho lo schema ma non riesco a convalidare questi file perché non sono documenti XML completo. Questi frammenti sono avvolti con gli elementi principali necessarie per formare XML valido quando vengono utilizzati in altri strumenti in modo non ho molta scelta a farli in XML valido o nel cambiare schema.

E 'possibile convalidare un elemento, piuttosto che l'intero documento? Se no, quali soluzioni alternative potrebbero essere suggeriti?

sto lavorando in C # con .NET 2.0 framework.

È stato utile?

Soluzione

Ho avuto un problema simile, dove ho potuto convalidare solo parti del mio documento XML. Mi si avvicinò con questo metodo qui:

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);
}

In sostanza, lo passo un XmlNode (che seleziono dall'intero XmlDocument mediante .SelectSingleNode), e uno schema XML, che si carica da un XSD risorsa incorporata dentro la mia app. Eventuali errori di convalida che potrebbero verificarsi sono infilati in un costruttore di stringa "errori", che ho poi letto alla fine, per vedere se si sono verificati errori registrati, oppure no.

funziona per me - la vostra situazione potrebbe essere diversa: -)

Altri suggerimenti

C'è un metodo XmlDocument.Validate che accetta un XmlNode come argomento una convalida solo questo nodo. Questo può essere quello che stai cercando ...

Ok, ecco un altro approccio:

Si potrebbe trasformare il vostro file di schema utilizzando una trasformazione XSLT in un nuovo schema che ha gli elementi frammento come root. Di 'lo schema originale sarebbe

<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>

Hai frammenti di tipo NestedElement che si desidera convalidare:

<NestedElement Name1="Name1" />

Allora si potrebbe utilizzare un modello XSLT come

<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>

Per creare un nuovo schema che ha NestedElement come root. Lo schema risultante sarà simile

<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>

È quindi possibile convalidare un documento frammento contro questo nuovo schema utilizzando un codice come

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 è lo schema originale, SchemaTransform.xslt è la trasformazione (come indicato sopra), rootelement.xml è un documento XML contenente un singolo nodo di frammento.

È possibile utilizzare uno speciale alias dello spazio dei nomi di destinare gli elementi che si desidera convalidare e quindi aggiungere solo schema per tale alias dello spazio dei nomi, ma non per gli altri. In questo modo solo gli elementi con il prefisso speciale dello spazio dei nomi avranno convalidato.

Non non sembra possibile fare ciò che aspiro a fare. Il mio lavoro attuale intorno è quello di creare un modello di documento XML vuoto. Quindi sostituire l'elemento desiderato con il mio snippet. Da lì, credo che il metodo validate sarebbe quindi vitale. Ma per creare questo modello sembra dinamicamente per essere un altro compito arduo a sé stante. Non sembra essere un modo semplice per creare un documento 'scheletro'.

Ho avuto lo stesso problema. Anche chiesto qui per la soluzione. Ho trovato una soluzione.

Il problema è che solo gli elementi root possono essere convalidati. Quindi ... posso modificare lo schema in memoria e aggiungere l'elemento / tipo di convalidare alla radice

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);
}

Solo un paio di linee e non si deve modificare o aggiungere qualsiasi file XSD :) Con questa semplice modifica lo schema in memoria, è possibile convalidare il frammento con lo stesso codice utilizzato per convalidare un documento completo. Basta essere sicuri che l'elemento principale del frammento di convalidare include lo spazio dei nomi. :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top