简体   繁体   English

验证xml节点,而不是整个文档

[英]Validating xml nodes, not the entire document

I'm working with some xml 'snippets' that form elements down the xml. 我正在使用一些xml'片段',它们在xml中形成元素。 I have the schema but I cannot validate these files because they are not complete xml documents. 我有架构,但我无法验证这些文件,因为它们不是完整的xml文档。 These snippets are wrapped with the necessary parent elements to form valid xml when they are used in other tools so I don't have much option in making them into valid xml or in changing the schema. 这些片段包含必要的父元素,以便在其他工具中使用时形成有效的xml,因此我没有太多选择将它们变为有效的xml或更改模式。

Is it possible to validate an element, rather than the whole document? 是否可以验证元素,而不是整个文档? If not, what workarounds could be suggested? 如果没有,可以提出哪些变通方法?

I'm working in C# with .NET 2.0 framework. 我正在使用.NET 2.0框架在C#中工作。

I had a similar problem where I could only validate parts of my XML document. 我有一个类似的问题,我只能验证我的XML文档的一部分。 I came up with this method here: 我在这里想出了这个方法:

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

Basically, I pass it an XmlNode (which I select from the entire XmlDocument by means of .SelectSingleNode), and an XML schema which I load from an embedded resource XSD inside my app. 基本上,我传递了一个XmlNode(我通过.SelectSingleNode从整个XmlDocument中选择),以及一个XML模式,我从我的app中的嵌入式资源XSD加载。 Any validation errors that might occur are being stuffed into a "errors" string builder, which I then read out at the end, to see if there were any errors recorded, or not. 可能发生的任何验证错误都被填充到“错误”字符串构建器中,然后我在最后读出,以查看是否记录了任何错误。

Works for me - your mileage may vary :-) 对我有用 - 你的里程可能会有所不同:-)

There is a XmlDocument.Validate method that takes an XmlNode as argument an validates only this node. 有一个XmlDocument.Validate方法,它将XmlNode作为参数,仅验证此节点。 That may be what you're looking for ... 那可能就是你要找的......

Ok, here's another approach: 好的,这是另一种方法:

You could transform your schema file using an XSLT transformation into a new schema that has your snippet elements as root. 您可以使用XSLT转换将模式文件转换为以snippet元素为根的新模式。 Say your original schema would be 说你的原始架构

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

You have snippets of type NestedElement that you want to validate: 您有要验证的NestedElement类型的片段:

<NestedElement Name1="Name1" />

Then you could use an XSLT template like 然后你可以使用像这样的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>

To create a new schema that has NestedElement as root. 创建以NestedElement为根的新架构。 The resulting schema would look like 结果模式看起来像

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

You can then validate a snippet document against this new schema using a code like 然后,您可以使用类似的代码针对此新架构验证代码段文档

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 is the original schema, SchemaTransform.xslt is the transformation (as shown above), rootelement.xml is an XML document containing a single snippet node. MySchema.xsd是原始模式, SchemaTransform.xslt是变换(如上所示), rootelement.xml是包含单一片段节点的XML文档。

I had the same problem. 我有同样的问题。 Even asked here for solution. 甚至在这里要求解决方案。 I have found a workaround. 我找到了一个解决方法。

The problem is that only root elements can be validated. 问题是只能验证根元素。 So... I edit the scheme IN MEMORY and add the element/type to validate to the root 所以...我编辑IN MEMORY方案并添加元素/类型以验证根

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

Just a couple of lines and you must not modify or add any XSD files :) With this simple change to your in-memory schema, you can validate the fragment with the same code you use to validate a full document. 只需几行,您就不能修改或添加任何XSD文件:)通过对内存模式的这种简单更改,您可以使用用于验证完整文档的相同代码验证该片段。 Just be sure that the root element of the fragment to validate includes the namespace. 只需确保要验证的片段的根元素包含命名空间。 :) :)

You can use a special namespace alias to earmark the elements you want to validate and then only add schema for that namespace alias but not for others. 您可以使用特殊的命名空间别名来标记要验证的元素,然后只为该命名空间别名添加模式,而不为其他人添加模式。 This way only those elements with your special namespace prefix will get validated. 这样,只有具有特殊名称空间前缀的元素才会被验证。

It doesn't not seem possible to do what I aspire to do. 似乎不可能做我渴望做的事情。 My current work around is to create a blank template xml document. 我目前的工作是创建一个空白模板xml文档。 Then replace the desired element with my snippet. 然后用我的代码片段替换所需的元素。 From there, I believe the Validate method would then be viable. 从那里,我相信Validate方法将是可行的。 But to create this template dynamically seems to be another daunting task in its own right. 但是动态创建这个模板似乎本身就是另一项艰巨的任务。 There doesn't seem to be any easy way to create a 'skeleton' document. 似乎没有任何简单的方法来创建“骨架”文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM