这个手册主要是讲,在XML文件中怎样使用Visual Basic,XML轴属性和LINQ toXML对象访问子和父元素。
子代
Visual Basic提供XML轴属性,可以很容易的引用子节点和标记。这是使用XML经常会遇到的情况。你可能会需要引用下一级元素在XML的数据层次上的不同层级上出现。那样的话,你可以使用XML 子代轴属性。
XML子代轴属性是用三个跟随着你想引用的XML元素的周期来定义的。例如,在手册1中用到的AdventureWorks contacts source文件中(你可以从手册1下载这个XML文件和相关的模式)。里面有个<AdditonalContactInfo>元素,包括了关于联系方式例如电话号码,发货和帐单地址等等的信息。在<AdditionalContactInfo>元素里面的电话号码可以出现在这个元素值里面的任何位置。最终,你就可以用XML子代轴属性来引用电话号码这个元素。例如:
Dim xmlDoc = XDocument.Load("AWContacts.xml")
' Return all descendant <telephoneNumber> elements
Dim telephoneNumbers = _
xmlDoc.<Contacts>.<Contact>.<aci:AdditionalContactInfo>...<act:telephoneNumber>
XML子代轴属性返回XML数据层次中所有符合元素的集合。我们看一个更加完整的例子。下面的方法用XML子代轴属性返回一串联系名字和电话号码。
Imports <xmlns="http://SampleSchema/AWContacts">
Imports <xmlns:s="sample-output">
Imports <xmlns:aci="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo">
Imports <xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
Public Class Recipe2
Public Function GetPhoneNumbers(ByVal xmlDoc As XDocument) As XElement
Return <s:ContactPhoneNumbers>
<%= From contact In xmlDoc.<Contacts>.<Contact> _
Where contact.<aci:AdditionalContactInfo>...<act:telephoneNumber>.<act:number>.Count > 0 _
Select <s:Contact>
<s:Name><%= contact.<FirstName>.Value & " " & _
contact.<LastName>.Value %></s:Name>
<s:PhoneNumbers>
<%= From number In _
contact.<aci:AdditionalContactInfo>...<act:telephoneNumber>.<act:number> _
Select <s:Number><%= number.Value %></s:Number> _
%>
</s:PhoneNumbers>
</s:Contact> _
%>
</s:ContactPhoneNumbers>
End Function
End Class
在XSLT中,同样传输是这样的:
<?xmlversion='1.0'?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aw="http://SampleSchema/AWContacts"
xmlns:s="sample-output"
xmlns:aci="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo"
xmlns:crm="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactRecord"
xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
<xsl:outputmethod="xml"indent="yes" />
<xsl:templatematch="aw:Contacts">
<s:ContactPhoneNumbers>
<xsl:apply-templatesselect="aw:Contact" />
</s:ContactPhoneNumbers>
</xsl:template>
<xsl:templatematch="aw:Contact">
<xsl:iftest="count(aci:AdditionalContactInfo//act:telephoneNumber/act:number) > 0">
<s:Contact>
<s:Name>
<xsl:value-ofselect="aw:FirstName"/>
<xsl:text> </xsl:text>
<xsl:value-ofselect="aw:LastName"/>
</s:Name>
<xsl:apply-templatesselect="aci:AdditionalContactInfo" />
</s:Contact>
</xsl:if>
</xsl:template>
<xsl:templatematch="aci:AdditionalContactInfo">
<s:PhoneNumbers>
<xsl:for-eachselect=".//act:telephoneNumber/act:number">
<s:Number>
<xsl:value-ofselect="."/>
</s:Number>
</xsl:for-each>
</s:PhoneNumbers>
</xsl:template>
</xsl:stylesheet>
一个比较重要的需要注意的是,当子元素的位置总是一样的时候就不应该用XML子代轴属性。如果用XML 子轴属性去引用XML数据层次中的特定位置,你的代码会比使用XML子代轴属性去搜索整个XML数据层次中符合的项执行起来好很多。
父代
XML轴属性使向下搜索XML数据层次快并且简单。然而,如果你想向上搜索XML数据层次呢?那样的话,你可以用XNode类的Ancestors方法。因为XML直接把LINQ to XML类的功能暴露出来,你可以用那些LINQ to XML类附带的功能。
Ancestors()这个方法在XML数据层次中向上搜索那些符合给出元素名字的元素。传给Ancestors方法的元素的名字必须包括元素XML命名空间。可以用GetXmlNamespace operator返回基于给出的XML的prefix的命名空间。对于默认的XML命名空间,调用GetXmlNamespace操作不传入prefix。如果你在同样的XML命名空间中搜索一个已经引用的元素,可以用Name.Namespace属性访问已经引用的元素的命名空间。
例如,下面的例子从AdventureWorks Contacts得到一串<telephoneNumber>元素(实际上,任何一个类型的phoneNumberType定义在ContactType.xsd文件里面),然后返回一串电话号码和跟电话号码相关的名字。这个例子调用Ancestors()方法去向上搜索XML数据层次中的<Contact>节点。
Imports <xmlns="http://SampleSchema/AWContacts">
Imports <xmlns:s="sample-output">
Imports <xmlns:aci="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo">
Imports <xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
Public Class Recipe2
Public Function GetPhoneList(ByVal numberList As IEnumerable(Of XElement)) As XElement
Return <s:PhoneNumberList>
<%= From number In numberList _
Let contact = number.Ancestors(GetXmlNamespace() + "Contact") _
Select <s:PhoneNumber>
<s:Number type=<%= number.Name.LocalName %>>
<%= number.<act:number>.Value %>
</s:Number>
<s:Owner><%= contact.<FirstName>.Value & " " & _
contact.<LastName>.Value %></s:Owner>
</s:PhoneNumber> _
%>
</s:PhoneNumberList>
End Function
End Class
在XSLT中,同样的传输是这样的:
<?xmlversion='1.0'?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aw="http://SampleSchema/AWContacts"
xmlns:s="sample-output"
xmlns:aci="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo"
xmlns:crm="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactRecord"
xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
<xsl:outputmethod="xml"indent="yes" />
<xsl:templatematch="aw:Contacts">
<s:PhoneNumberList>
<xsl:apply-templatesselect="aw:Contact//act:telephoneNumber" />
</s:PhoneNumberList>
</xsl:template>
<xsl:templatematch="aw:Contact//act:telephoneNumber">
<s:PhoneNumber>
<s:Number>
<xsl:attributename="type">
<xsl:value-ofselect="name()" />
</xsl:attribute>
<xsl:value-ofselect="./act:number"/>
</s:Number>
<s:Owner>
<xsl:value-ofselect="ancestor::aw:Contact/aw:FirstName"/>
<xsl:text> </xsl:text>
<xsl:value-ofselect="ancestor::aw:Contact/aw:LastName"/>
</s:Owner>
</s:PhoneNumber>
</xsl:template>
</xsl:stylesheet>
打印 | 张贴于 2008-10-28 14:16:47 | Tag:VB Team Blog LINQ Cookbook
留言反馈