Linq到XML命名空间问题



问候语,

我的目标:验证XML文档,然后将数据加载到自定义对象中。我正在使用Linq-to-XML。

我的处境:我正在为命名空间和/或Linq语法而挣扎。我以为一切都正常。代码读取XML并加载对象,但实现了XDocument.Valide传递了所有内容,而不是真正验证。我想这是不严格的验证。为了验证XDocument.Valide((方法,我在XML文件中添加了一个Namespace。验证有效,但现在我的LinqQuery创建的XElement在尝试访问.Element("Field"(.value.时返回null

我的问题:

  1. 如何既验证XML文档又访问元素的值?除了使用XDocument.Valide之外,我是否应该使用另一个流程来根据XSD验证XML
  2. 我的Linq查询中有问题吗
  3. 当我试图在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。我结合他们的回答找到了答案。我对上面的代码有三个问题。

  1. XSD中缺少targetNamespace
  2. 我需要在我的Linq查询中添加命名空间,如Tim Jarvis和Broken Glass所示
  3. 我需要在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;

相关内容

  • 没有找到相关文章

最新更新