Проблемы Linq to XML Namespace - PullRequest
       2

Проблемы Linq to XML Namespace

1 голос
/ 06 апреля 2011

Привет,

Моя цель: Чтобы проверить документ XML, затем загрузить данные в пользовательский объект.Я использую Linq для XML.

Моя ситуация: Я борюсь с пространством имен и / или синтаксисом Linq.Я думал, что все работает.Код читает XML и загружает объект, но понял, что XDocument.Validate все пропускает и не проверяет.Я думаю, что это слабая проверка.Чтобы проверить метод XDocument.Validate (), я добавил пространство имен в файл XML.Проверка работает, но теперь XElement, созданный моим Linq Query, возвращает ноль при попытке доступа к .Element («Поле»). Value.

Мои вопросы:

  1. Как я могу проверить документ XML и получить доступ к значению Элементов?Должен ли я использовать другой процесс для проверки XML по XSD помимо использования XDocument.Validate?
  2. Проблема в моем запросе Linq?
  3. Когда я пытаюсь указать конкретный элемент в запросе Linq, я никогда не получаю результаты.Он работает только тогда, когда он

    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 есть пространство имен.Если пространства имен нет, этот код выполняет слабую проверку, но может прочитать значение.

Предложения?

Ответы [ 3 ]

1 голос
/ 08 апреля 2011

Спасибо Тиму Джарвису и Битлен Гласс.Я нашел ответ, объединив их ответы.У меня было три проблемы с приведенным выше кодом.

  1. Мне не хватало targetNamespace в XSD.
  2. Мне нужно было добавить пространство имен в мой запрос Linq , как указано ТимомДжарвис и битое стекло.
  3. Мне нужно было добавить пространство имен в параметре XName в XElement.Element .

См. Исправленный код ниже.

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();

Спасибо!

1 голос
/ 06 апреля 2011

вам нужно включить пространство имен в вызов.

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;
0 голосов
/ 06 апреля 2011

Вы должны объявить и использовать пространство имен:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...