问候语,
我的目标:验证XML文档,然后将数据加载到自定义对象中。我正在使用Linq-to-XML。
我的处境:我正在为命名空间和/或Linq语法而挣扎。我以为一切都正常。代码读取XML并加载对象,但实现了XDocument.Valide传递了所有内容,而不是真正验证。我想这是不严格的验证。为了验证XDocument.Valide((方法,我在XML文件中添加了一个Namespace。验证有效,但现在我的LinqQuery创建的XElement在尝试访问.Element("Field"(.value.时返回null
我的问题:
- 如何既验证XML文档又访问元素的值?除了使用XDocument.Valide之外,我是否应该使用另一个流程来根据XSD验证XML
- 我的Linq查询中有问题吗
-
当我试图在Linq查询中指定一个特定的Element时,我永远不会得到结果。它仅在时有效
IEnumerable<XElement> residents = from xeRes in xD.Elements() select xeRes;
但是
IEnumerable<XElement> residents = from xeRes in xD.Elements("Resident") select xeRes;
不返回任何内容。
欢迎提出任何建议。
谢谢你,
代码段:
XSD
<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns="http://kinduit.net/ResidentNS" xmlns:schema="http://kinduit.net/ResidentNS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified"><xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Resident">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FacilityID">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID2" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>...
XML
<?xml version="1.0"?><Resident xmlns="http://kinduit.net/ResidentNS">
<FacilityID>WARMSPRINGS</FacilityID>
<ResidentID>WS585459</ResidentID>
<ResidentID2>145214</ResidentID2>...
C#
// Validate XML Schema...
XmlSchemaSet sc = new XmlSchemaSet();
XNamespace xNs = "http://kinduit.net/ResidentNS";
try
{
// Validate against the XSD...
string location = System.Reflection.Assembly.GetAssembly(typeof(ElementsBC.Interface)).Location;
sc.Add(xNs.ToString(), location.Replace("ElementsBC.dll", "") + "\InterfaceXSD\resident.xsd");
XDocument xD = this.ConvertToXDocument(ResidentXML);
xD.Validate(sc, (sender, e) => { throw new Exception(e.Message); }, true);
IEnumerable<XElement> residents =
from xeRes in xD.Elements()
select xeRes;
counts[0] = residents.Count();
foreach (XElement el in residents)
{
try
{
// get facility...
string facilityid = el.Element("FacilityID").Value.ToString();
如果XML中存在Namespace,则最后一行返回null。如果没有Namespace,则此代码运行lax Validation,但可以读取值。
建议?
您需要在调用中包含名称空间。
XNamespace ns = xD.GetDefaultNamespace() // Or some other way of getting the namespace you want.
IEnumerable<XElement> residents = from xeRes in xD.Elements(ns + "Resident")
select xeRes;
感谢Tim Jarvis和Broken Glass。我结合他们的回答找到了答案。我对上面的代码有三个问题。
- XSD中缺少targetNamespace
- 我需要在我的Linq查询中添加命名空间,如Tim Jarvis和Broken Glass所示
- 我需要在XElement.Element的XName参数中添加Namespace
请参阅下面的更正代码。
XSD
<?xml version="1.0" encoding="utf-8"?><xsd:schema xmlns:xs="http://kinduit.net/ResidentNS" targetNamespace="http://kinduit.net/ResidentNS" xmlns="http://kinduit.net/ResidentNS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Resident">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FacilityID">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID2" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>...
XML:没有更改
C#
// Validate XML Schema...
XmlSchemaSet sc = new XmlSchemaSet();
XNamespace xNs = "http://kinduit.net/ResidentNS";
try
{
// Validate against the XSD...
string location = System.Reflection.Assembly.GetAssembly(typeof(ElementsBC.Interface)).Location;
sc.Add(xNs.ToString(), location.Replace("ElementsBC.dll", "") + "\InterfaceXSD\resident.xsd");
XDocument xD = this.ConvertToXDocument(ResidentXML);
xD.Validate(sc, (sender, e) => { throw new Exception(e.Message); }, true);
IEnumerable<XElement> residents =
from xeRes in xD.Elements(xNs + "Resident")
select xeRes;
counts[0] = residents.Count();
foreach (XElement el in residents)
{
try
{
// get facility...
string facilityid = el.Element(xNs + "FacilityID").Value.ToString();
谢谢!
您必须声明并使用名称空间:
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
此外,XML中没有Resident
元素——有些名为element
的元素的属性name
以"Resident"开头。这些元素不是根节点的直接子级,因此在查询中必须使用Descendands()
而不是Elements()
。
已经说过这对我有效(返回3个节点(:
XDocument xD = XDocument.Load("test.xml");
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
IEnumerable<XElement> residents = from xeRes in xD.Descendants(xsd + "element")
where xeRes.Attribute("name") != null
&& xeRes.Attribute("name").Value.StartsWith("Resident")
select xeRes;