전체 문서가 아닌 XML 노드를 확인합니다
-
23-08-2019 - |
문제
XML 아래로 요소를 형성하는 XML '스 니펫'으로 작업하고 있습니다. 스키마가 있지만이 파일은 완전한 XML 문서가 아니기 때문에이 파일을 검증 할 수 없습니다. 이 스 니펫은 다른 도구에 사용될 때 유효한 XML을 형성하기 위해 필요한 상위 요소로 싸여 있으므로 유효한 XML로 만들거나 스키마를 변경하는 데 많은 옵션이 없습니다.
전체 문서보다는 요소를 검증 할 수 있습니까? 그렇지 않다면 어떤 해결 방법을 제안 할 수 있습니까?
.NET 2.0 프레임 워크와 함께 C#에서 작업하고 있습니다.
해결책
XML 문서의 일부만 검증 할 수있는 비슷한 문제가있었습니다. 이 방법을 여기에서 생각해 냈습니다.
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);
}
기본적으로 XMLNode (.SelectSingLenode를 통해 전체 XMLDocument에서 선택한 XMLDocument에서 선택) 및 앱 내부 리소스 XSD에서로드하는 XML 스키마를 전달합니다. 발생할 수있는 유효성 검사 오류는 "오류"문자열 빌더로 채워져서 끝에 읽은 다음 오류가 기록되어 있는지 여부를 확인합니다.
나를 위해 일합니다 - 당신의 마일리지는 다를 수 있습니다 :-)
다른 팁
이있다 XmlDocument.Validate
방법을 취하는 방법 XmlNode
인수 로서이 노드 만 검증합니다. 그게 당신이 찾고있는 것일 수 있습니다 ...
좋아, 여기 또 다른 접근법이있다 :
XSLT 변환을 사용하여 스키마 파일을 스 니펫 요소를 루트로 갖는 새 스키마로 변환 할 수 있습니다. 원래 스키마가 될 것이라고 말하십시오
<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>
당신은 유형의 스 니펫이 있습니다 NestedElement
검증을 원한다는 것 :
<NestedElement Name1="Name1" />
그런 다음 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>
새로운 스키마를 만들려면 NestedElement
루트로. 결과 스키마는 모양이 될 것입니다
<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>
그런 다음 코드와 같은 코드를 사용 하여이 새 스키마에 대해 스 니펫 문서를 검증 할 수 있습니다.
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
원래 스키마, SchemaTransform.xslt
변환 (위와 같이), rootelement.xml
단일 스 니펫 노드를 포함하는 XML 문서입니다.
특수 네임 스페이스 별명을 사용하여 검증하려는 요소를 배정 한 다음 해당 네임 스페이스 별칭에 대한 스키마를 추가 할 수 있지만 다른 사람은 그렇지 않습니다. 이 방법으로 특수 네임 스페이스 접두사가있는 요소 만 검증됩니다.
내가 열망하는 일을하는 것은 불가능한 것 같지 않습니다. 현재의 작업은 빈 템플릿 XML 문서를 만드는 것입니다. 그런 다음 원하는 요소를 내 스 니펫으로 교체하십시오. 거기에서 나는 검증 방법이 실행 가능하다고 생각합니다. 그러나이 템플릿을 동적으로 만드는 것은 그 자체로 또 다른 어려운 작업 인 것 같습니다. '골격'문서를 만드는 쉬운 방법은없는 것 같습니다.
나는 같은 문제가 있었다. 여기서 해결책을 요청했습니다. 해결 방법을 찾았습니다.
문제는 루트 요소 만 검증 될 수 있다는 것입니다. 그래서 ... 메모리에서 체계를 편집하고 루트에 검증하기 위해 요소/유형을 추가합니다.
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);
}
몇 줄 만 있으면 XSD 파일을 수정하거나 추가해서는 안됩니다. :) Memory Inmory 스키마를 간단하게 변경하면 전체 문서를 검증하는 데 사용하는 것과 동일한 코드로 조각을 검증 할 수 있습니다. 검증 할 조각의 루트 요소에 네임 스페이스가 포함되어 있는지 확인하십시오. :)