2011-12-20 5 views
0

필자는 요소 재정렬이 필요한 XML을 가지고있다. LINQ를 사용하여이 작업을 수행 할 수 있습니까?LINQ를 사용하여 XSD에 맞게 XML을 변경할 수 있습니까?

아래와 같이 요소 3과 2가 섞여서 요소가 1,2와 3이되도록 재정렬해야합니다. 다음 번에 데이터가 들어올 때 순서가 달라 지지만 순서는 달라집니다. 1,2 및 3으로 되돌릴 필요가 있습니다.

<a> 
    <1></1> 
    <3></3> 
    <2></2> 
</a> 
+1

물론 XML을 다시 작성하고 하위 XElement를 올바른 순서로 넣으면됩니다. 올바른 주문이 무엇인지 어떻게 알 수 있습니까? XSD를'XmlSchema'에 로딩하고'XmlSchemaSequence' 클래스를 사용합니다. 내 질문보기 (내 대답) http://stackoverflow.com/questions/7311880/xmlschema-inferred-from-an-xml-file-how-to-iter-through-all-the-elements-in 정보. –

+0

@Morawski 그래서 코드가하는 일은 프로젝트의 모든 요소와 속성을 통해 실행됩니다.내 1,2,3 예제에서는 충분히 쉽지만 요소가 여러 번 나타날 가능성이있는 경우 요소가 몇 번 발생했는지 계산해야하고 그 수를 반복해야합니까? – Andy

답변

3

가장 어려운 부분은 XSD에서 올바른 순서를 얻는 것입니다. XSD를 XDocument으로로드하고 XML로 직접 쿼리 할 수 ​​있습니다.

당신의 예에 따라 다음 스키마를 고려하면 객체 (이 점을로드하면

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema id="XMLSchema1" 
    targetNamespace="http://tempuri.org/XMLSchema1.xsd" 
    elementFormDefault="qualified" 
    xmlns="http://tempuri.org/XMLSchema1.xsd" 
    xmlns:mstns="http://tempuri.org/XMLSchema1.xsd" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
> 

    <xs:complexType name="a"> 
    <xs:sequence> 
     <xs:element name="_1" type="xs:string" minOccurs="1" maxOccurs="1" /> 
     <xs:element name="_2" type="xs:string" minOccurs="1" maxOccurs="1" /> 
     <xs:element name="_3" type="xs:string" minOccurs="1" maxOccurs="1" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> ` 

(나는 & 3 스스로 유효하지 않은 XML 이름입니다, 1, 2 이후 밑줄을 추가) XDocument 또는 XElement 가장 좋습니다), 당신은 스키마에서 LINQ 쿼리를 수행 할 수 있습니다. (쿼리는 테스트되지 않았습니다. 마지막으로이 작업을 메모리에서 수행합니다.하지만 누락 된 부분이 있으면 올바른 방향으로 가리켜 야합니다)

var schema = XDocument.Load(@"C:\somepath\XMLSchema1.xsd"); 
var xs = XNamespace.Get(@"http://www.w3.org/2001/XMLSchema"); 

var order = (from x in schema.Elements(xs + "schema").Elements(xs + "complexType") 
      where x.Attributes("name").FirstOrDefault().Value == "a" 
      select x.Element(xs + "sequence").Elements()) 
      .First() 
      .Select(x => x.Attribute("name").Value); 

미리 정의 된 유형 및/또는 사용자 정의 네임 스페이스가있는 좀 더 복잡한 XSD를 사용하면 요소의 순서를 더 복잡하게 만드는 쿼리를 만들지 만 잘하면 아이디어를 얻을 수 있습니다. 매우 복잡한 XSD를 사용하는 경우 XmlSchemaInfo 개체 모델을 이해하는 데 도움이되도록이 대답의 끝 부분에있는 링크 중 일부를 참조하십시오. 그러면 순서를 훨씬 쉽게 쉽게 작성할 수있는 고유 한 쿼리를 작성할 수 있습니다.

올바른 순서를 정한 후에는 LINQ를 사용하여 노드 순서를 실제로 변경하는 것을 권장하지 않습니다. LINQ는 개체를 수정하기 위해 설계된 것이 아니기 때문에 노드와 부모 노드를 찾은 다음 다시 배열하는 것입니다. 당신이 원하는 순서대로.

XElement xelem = // get parent element of the elements you need to rearrange 

foreach (var element in order) 
{ 
    var node = xelem.Element(element); 
    node.Remove(); 
    xelem.Add(node);     
} 

자주 코드에서 직접 XSD 접근과 협력 위하여려고하는 경우에, 나는 XmlSchemaInfo 개체 모델이 잘 설명되지 않는 도움을 다음의 질문과 답변을 읽어 보시기 바랍니다, 그리고 약간의 시간을에 & 노력을 할 것이다 필요한 것을 추출 할 수있는 실행 가능한 방법을 얻으십시오. 스키마에서 필요한 정보를 쉽게 찾고 추출 할 수 있습니다.

XmlSchema inferred from an XML file - how to iterate through all the elements in the XSD? (Morawski의 질문은 그의 주석에서 참조)

Capture Schema Information when validating XDocument (내 자신의 질문 & 답) 나는에 대한 정보의 대부분을 가지고있는 곳에서

In C#, how to determine the XSD-defined MaxLength for an element

http://geekswithblogs.net/.NETonMyMind/archive/2006/05/02/76957.aspx (위대한 블로그 포스팅 내 SchemaInfo 질문과 답변

+0

아직도 답장을 보내 주셔서 감사합니다. LINQ 쿼리를 변경해야하는 몇 가지 사소한 것들이 있었는지, 만약 당신이 정확성에 대한 질문에 그것을 업데이 트하려면 내가 그것을 변경했다 -> var order = (from x from schema.Elements (xs + "schema ") .Elements (xs +"complexType ") 여기서 x.Attributes ("name "). FirstOrDefault(). 값 =="a " select x.Element (xs +"sequence ") 요소() .First() .Select (x => x.Attribute ("name"). Value); – Andy

+0

@Andy, 고마워 .... 고쳤다. – psubsee2003

관련 문제