чтение CDATA с linq to xml - PullRequest
       10

чтение CDATA с linq to xml

2 голосов
/ 01 мая 2009

У меня есть следующий XML-файл, и я не могу понять, как получить значение в элементах (которые похоронены в CDATA). Я пытаюсь использовать linq для xml для этого. Если кто-то знает, как вы можете преобразовать это в объект «Продукт» (предположим, у нас есть объект продукта, свойства которого имеют те же имена, что и у элементов). Заранее спасибо.

боб

<CNETResponse realm="cnet" version="1.0" xmlns="http://api.cnet.com/rest/v1.0/ns" xmlns:xlink="http://www.w3.org/1999/xlink">
<TechProduct id="33517677">
    <Name><![CDATA[Nikon CoolPix L20 (deep red)]]></Name>
    <Topic id="1670"></Topic>
    <ImageURL width="60"><![CDATA[http://i.i.com.com/cnwk.1d/sc/33517677-2-60-0.gif]]></ImageURL>
</TechProduct>
</CNETResponse>

Ответы [ 2 ]

2 голосов
/ 01 мая 2009

Проблема в пространствах имен - например, что-то вроде:

XNamespace ns = "http://api.cnet.com/rest/v1.0/ns";
XElement techProd = doc.Root.Element(ns + "TechProduct");

Product product = new Product {
    Id = (int)techProd.Attribute("id"),
    Name = techProd.Element(ns + "Name").Value,
    Topic = techProd.Element(ns + "Topic").Value,
    TopicId = (int)techProd.Element(ns + "Topic").Attribute("id"),
    ImageUrl = techProd.Element(ns + "ImageURL").Value,
    ImageWidth = (int)techProd.Element(ns + "ImageURL").Attribute("width"),
};

Вы также можете предпочесть XmlSerializer - что-то вроде:

XmlSerializer ser = new XmlSerializer(typeof(CnetResponse));
CnetResponse response = (CnetResponse)ser.Deserialize(new StringReader(xml));
TechProduct product = response.TechProduct;

С определениями классов, такими как:

[Serializable, XmlRoot("CNETResponse", Namespace = CnetResponse.Namespace)]
public class CnetResponse {
    public const string Namespace = "http://api.cnet.com/rest/v1.0/ns";
    public TechProduct TechProduct { get; set; }
}
[Serializable, XmlType(Namespace = CnetResponse.Namespace)]
public class TechProduct
{
    [XmlAttribute("id")]
    public int Id { get; set; }
    public string Name {get;set;}
    public Topic Topic { get; set; }
    [XmlElement("ImageURL")]
    public Image Image { get; set; }        
}
[Serializable, XmlType(Namespace = CnetResponse.Namespace)]
public class Topic {
    [XmlAttribute("id")]
    public int Id { get; set; }
    [XmlText]
    public string Text {get;set;}
}
[Serializable, XmlType(Namespace = CnetResponse.Namespace)]
public class Image {
    [XmlAttribute("width")]
    public int Width { get; set; }
    [XmlText]
    public string Url {get;set;}
}

Или, в качестве альтернативы, просто запустите xml через xsd.exe, чтобы получить подходящий код C #:

xsd foo.xml
xsd foo.xsd /classes
1 голос
/ 01 мая 2009

Предполагая, что ваш класс Product имеет используемый здесь конструктор, попробуйте это, где rawXml - это XML-ответ CNET:

XElement cnetResponse = XElement.Parse(rawXml);

IEnumerable<NameQty> products =
    from e in cnetResponse.Descendants("TechProduct")
    select new Product(
        (string)e.Element("Name"),
        (int)e.Element("Topic").Attribute("id"),
        (string)e.Element("ImageURL")
    );

foreach(Product p in products)
{
    // do stuff
}

У меня нет доступа к машине, на которой можно это проверить, поэтому я не даю никаких гарантий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...