2009-04-03 5 views
4

XML을 구성하는 일부 XML '스 니펫'을 사용하고 있습니다. 스키마가 있지만 완전한 xml 문서가 아니기 때문에이 파일의 유효성을 검사 할 수 없습니다. 이 스 니펫은 다른 도구에서 사용될 때 유효한 xml을 형성하는 데 필요한 부모 요소로 싸여 있으므로 XML을 유효하게하거나 스키마를 변경하는 데 많은 옵션이 없습니다.전체 문서가 아닌 XML 노드 유효성 확인

전체 문서가 아닌 요소의 유효성을 검사 할 수 있습니까? 그렇지 않은 경우 어떤 대안을 제안 할 수 있습니까?

저는 C# .NET 2.0 프레임 워크로 작업하고 있습니다.

+0

Xml을로드해야하는 XmlDocument의 루트 노드를 사용할 수없는 경우'SelectSingleNode'를 어떻게 사용할 수 있을지 모르겠습니다. 유효하지 않은 경우 실패합니다. 문서 자체가 유효하지 않으면'XPath'를 사용할 수 없다고 생각합니다. 그렇게 할 방법이 있습니까? –

답변

4

XML 문서의 일부만 유효성을 검사 할 수있는 유사한 문제가있었습니다. 나는 내부에 포함 된 리소스의 XSD에서로드 기본적으로

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

, 나는 그것을 (내가 .SelectSingleNode에 의해 전체 XmlDocument에서 선택)하는 XMLNode를 전달하고 XML 스키마 : 여기이 방법을 함께했다 내 애플 리케이션. 발생할 수있는 모든 유효성 검증 오류는 "오류"문자열 빌더에 채워지고, 그 다음에는 오류를 기록했는지 여부를 읽습니다.나를 위해

작품 - 저도 같은 문제가 있었다

+0

이 솔루션은 상당히 잘 작동합니다. 사실 이것은 지금 문서에 대한 유효성 확인과 현저하게 비슷합니다. 나는 그것이 개별 노드에도 적용될 수 있다는 것을 몰랐다. 되돌아 보면, 루트가 그 자체로 노드라고 가정합니다. – ipwnponies

+0

감사합니다, 마크! 이것은 나에게 많은 도움이되었습니다. – Kizz

+0

Marc,'XmlTextReader'를 사용하지 않고'using' 블록을 사용하여이 답을 편집 할 수 있습니까? 방금이 코드 복사/붙여 넣기를 보았습니다. –

0

특수 네임 스페이스 별칭을 사용하여 유효성을 검사 할 요소를 지정한 다음 해당 네임 스페이스 별칭에 대한 스키마 만 추가하고 다른 스키마에는 별칭을 추가 할 수 있습니다. 이렇게하면 특수 네임 스페이스 접두사가있는 요소 만 유효성이 검사됩니다.

+0

내가 이해하는 것으로부터, 이것은 편집/생성 스키마를 필요로하기 때문에 적합하지 않을 것이다. 매년 다른 사람이 사용하고 업데이트하는 프로토콜이기 때문에 스키마를 변경할 수 없습니다. 내부 도구 만 작성하므로 유지 관리가 최소한으로 유지되어야합니다. – ipwnponies

2

XmlDocument.Validate 메서드는 인수로 XmlNode을 사용하고이 노드의 유효성을 검사합니다. 그것은 당신이 찾고있는 것일 수도 있습니다 ...

+0

불행히도 지금 현재 내 프로젝트에 액세스 할 수 없으므로이를 확인할 수 없습니다. 하지만 MSDN을 읽는 것만으로도 이것이 내가 찾고있는 것 같습니다. 이 모든 시간, 나는 XmlSchema 아래에서 찾고 있었어 ... – ipwnponies

+0

이것은 작동하지 않습니다. 유효성을 검사 할 노드는 정확한 '깊이'에 있어야합니다. 이 방법은 xml 파일의 유효성을 부분적으로 확인하려는 경우 유용합니다. 나는 유효한 XML 파일이 없다. – ipwnponies

0

내가하고자하는 일은 불가능하지 않습니다. 내 현재 해결 방법은 빈 템플릿 XML 문서를 만드는 것입니다. 그런 다음 원하는 요소를 스 니펫으로 바꿉니다. 거기에서 Validate 메서드가 실행 가능할 것이라고 믿습니다. 그러나이 템플릿을 동적으로 생성하는 것은 또 다른 어려운 작업입니다. '해골'문서를 만드는 쉬운 방법이없는 것 같습니다.

루트로 당신의 조각 요소를 가진 새 스키마로 XSLT 변환을 사용하여 스키마 파일을 변환 할 수 :

+0

제 생각에는 XSLT가 유용 할 수 있습니다. 몇 가지 제안에 대한 나의 새로운 대답을보세요 – MartinStettner

1

좋아, 여기에 또 다른 방법입니다.

<NestedElement Name1="Name1" /> 

그런 다음 당신은을 만들려면

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

같은 XSLT 템플릿을 사용할 수 있습니다 : 원래 스키마가 당신이 유효성을 검사 할 유형 NestedElement의 조각이

<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을 루트로 사용합니다. 결과 스키마 (위 그림 참조) SchemaTransform.xslt가 변화하고, 원래의 스키마가 그런 다음

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 같은 코드를 사용하여이 새 스키마에 대한 조각 문서의 유효성을 검사 할 수 있습니다

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

과 같을 것이다 , rootelement.xml은 단일 스 니펫 노드가 포함 된 XML 문서입니다.

+0

이것은 매우 우아한 해결책입니다. 그러나 그것을 사용하지 못하게하는 한 가지가 있습니다. 변환을 위해서는 'NestedElement'에 대한 지식이 필요합니다. 이는 제 3 자에 의한 스키마 업데이트가있을 수 있으며 xslt에 대한 업데이트/유지 관리가 필요하기 때문에 문제가됩니다. – ipwnponies

+0

요소 이름 (즉, 'NestedElememt')을 매개 변수로 만들고 코드 내의 스 니펫 최상위 요소에서 읽을 수 있습니다. 그렇다면 다중 스 니펫 엘리먼트에 대해서도 작동합니다 ... – MartinStettner

+0

시간이 있다면 아마도 "feeding"매개 변수 트릭을 시연 할 수 있습니다. 나는 이것에 3-4 시간을 문자 그대로 낭비했고, 아무 곳에도 가지 않았다. 실제로, 매개 변수를 먹이는 것은 쉽다, 속임수는 XSLT 1.0에 그것을 사용하기위한 것이다 : http://stackoverflow.com/questions/6117460/xsl-how-to-use-parameter-inside-match 그러나 나는 결코 아무데도, 즉 없다 템플릿은 내가 원한 것과 결코 매치하지 않았다. 문자열로 간다. 지금은 모든 것을 바꿔라. 우스꽝 스럽다. +1 솔루션. –

0

:-) 귀하의 마일리지가 다를 수 있습니다. 심지어 해결책을 묻는 질문. 해결 방법을 찾았습니다.

문제는 루트 요소 만 유효성을 검사 할 수 있다는 것입니다. 그래서 ... 나는 MEMORY IN 계획을 편집하고 루트

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 파일을 :) 추가하지 않아야합니다 메모리 내 스키마의 경우 전체 문서의 유효성을 검사하는 데 사용하는 코드와 동일한 코드로 조각을 유효화 할 수 있습니다. 유효성을 검사 할 조각의 루트 요소에 네임 스페이스가 포함되어 있는지 확인하십시오. :)

관련 문제