2011-12-20 1 views
0

У меня есть XML, который нуждается в его перестановке элементов. Есть ли способ сделать это с помощью LINQ?Можете ли вы изменить XML, чтобы он соответствовал XSD с LINQ?

Как и в приведенном ниже примере, элементы 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-iterate-through-all-the-elements-in для более Информация. –

+0

@Morawski Так что ваш код выполняется через каждый элемент и атрибут в проекте.Для моего примера 1,2,3, кажется, достаточно легко, но если бы существовала возможность появления элемента несколько раз, вам нужно было бы подсчитать, сколько раз элемент возникает и зацикливать этот номер? – Andy

ответ

3

Самая сложная часть - получить правильный заказ от XSD. Вы можете загрузить XSD как XDocument и запросить его непосредственно с помощью XML.

Рассмотрим следующую схему на основе вашего примера (я добавил подчеркивание так 1, 2, & 3 не допустимые имена 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> ` 

Если вы загрузите это в объект (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? (вопрос Моравский, он ссылается в своем комментарии)

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 = (от x в схеме schemaElements (xs + " ") .Elements (xs +" complexType ") где x.Attributes (" name "). FirstOrDefault(). Значение ==" a " выберите x.Element (xs +" sequence "). Элементы()) .First() .Выберите (x => x.Attribute («имя»). Значение); – Andy

+0

@ Энди, спасибо .... исправлено. – psubsee2003

Смежные вопросы