2011-12-20 80 views
0

我有一个XML需要它的元素重新排列。有没有办法使用LINQ来做到这一点?你可以通过LINQ更改XML以适应XSD吗?

在下面的例子中,元素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 for more信息。 – 2011-12-20 09:29:37

+0

@Morawski所以你的代码做的是贯穿项目中的每个元素和属性。对于我的1,2,3示例来说,似乎很容易,但是如果元素有多次出现的可能性,您是否需要计算元素出现的次数并循环该数字? – Andy 2011-12-20 10:03:06

回答

3

最难的部分是从XSD获得正确的顺序。您可以将XSD加载为XDocument,然后直接使用XML进行查询。

考虑根据你的榜样下面的架构(我加了下划线,因为12,& 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> ` 

如果加载到一个对象(本XDocumentXElement是最好的),你可以在模式上做一个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 =(从schema.Elements(xs +“schema中的x “).Elements(xs +”complexType“) 其中x.Attributes(”name“)。FirstOrDefault()。值==”a“ select x.Element(xs +”sequence“)。Elements()) 。First() .Select(x => x.Attribute(“name”)。Value); – Andy 2011-12-20 11:21:43

+0

@安迪,谢谢....修正。 – psubsee2003 2011-12-20 11:42:41

相关问题