C # / XML - Вопрос - PullRequest
       4

C # / XML - Вопрос

0 голосов
/ 31 августа 2010

У меня есть проблема, которую я пытаюсь решить почти неделю, но, похоже, я, к сожалению, не могу справиться с ней самостоятельно. Может быть, кто-нибудь может мне помочь.

У меня есть этот тип исходного XML:

<data> 
<para1>24499</para1> 
<para2>32080148</para2> 
<para4>20e500cc6008d0f8ab1fd108b220ca261f85edd9</para4> 
<para6></para6> 
<timetype>4</timetype> 
<fkcontent>964342</fkcontent> 
<season>0</season> 
<fmstoken><![CDATA[7bca3c544ad64e526806fb5a6b845148]]></fmstoken> 
<fmstoken_user>32010484</fmstoken_user> 
<fmstoken_time>1283165972</fmstoken_time> 
<fmstoken_renew><![CDATA[http://www.sky.com/logic/fmstoken.php?method=refresh]]></fmstoken_renew> 
<adserverXML><![CDATA[http://www.sky.de/dummy.xml]]></adserverXML> 
    <playlist> 
<videoinfo quality="0" name="DSL 1000"> 
    <id>24499</id> 
    <noad>1</noad> 
    <productplacement>0</productplacement> 
    <filename>http://www.sky.com/video/1/V_53511_BB00_E81016_46324_16x9-lq-512x288-vp6-c0_bbb491b3ce64ef667340a21e2bfb3594.f4v</filename> 
    <title><![CDATA[Who will be the winner?]]></title> 

    </videoinfo> 
<videoinfo quality="1" name="DSL 2000"> 
    <id>24499</id> 
    <noad>1</noad> 
    <productplacement>0</productplacement> 
    <filename>http://www.sky.de/video/1/V_53513_BB00_E81016_46324_16x9-hq-512x288-vp6-c0_fa948bc5429cf28455779666cc59cf5e.f4v</filename> 
    <title><![CDATA[Who will be the winner?]]></title> 

    </videoinfo> 
    </playlist> 
</data>

А вот части кода, которые позволяют мне получать необходимое содержимое тега со страницы XML выше:

        private static string getTagContent(string source, string tag)
    {
        string fullTagBegin = "<" + tag + ">";
        string fullTagEnd = "</" + tag + ">";

        int indexBegin = source.IndexOf(fullTagBegin) + fullTagBegin.Length;
        int indexEnd = source.IndexOf(fullTagEnd);
        int indexLength = indexEnd - indexBegin;

        if (indexBegin == -1 || indexEnd == -1)
            return "UNKNOWN";
        return source.Substring(indexBegin, indexLength);
    }



    public static void Start(String url)
    {
        try
        {
            String urlXML = url;
            WebClient wClient = new WebClient();

            string sourceXML = wClient.DownloadString(urlXML);
            sourceXML = sourceXML.Replace("]]>", "");
            sourceXML = sourceXML.Replace("<![CDATA[", "");


            String para1 = getTagContent(sourceXML, "para1");
            String para2 = getTagContent(sourceXML, "para2");
            String para4 = getTagContent(sourceXML, "para4");
            String timetype = getTagContent(sourceXML, "timetype");
            String fkcontent = getTagContent(sourceXML, "fkcontent");
            String season = getTagContent(sourceXML, "season");
            String fmstoken = getTagContent(sourceXML, "fmstoken");
            String fmstoken_user = getTagContent(sourceXML, "fmstoken_user");
            String fmstoken_time = getTagContent(sourceXML, "fmstoken_time");
            String fmstoken_renew = getTagContent(sourceXML, "fmstoken_renew");
            String filename = getTagContent(sourceXML, "filename").Replace("http://", "");
            String title = System.Text.RegularExpressions.Regex.Replace(getTagContent(sourceXML, "title"), @"[^a-zA-Z0-9]","_");

Проблема:

все работает нормально, за исключением того факта, что в исходном XML есть два тега "filename" и "title", но мне нужно выбрать только вторые, те, которые находятся под этой строкой:

<videoinfo quality="1" name="DSL 2000">

и каким-то образом пропустить / игнорировать первые, те, которые находятся выше предыдущей строки и прямо под этой строкой:

<videoinfo quality="0" name="DSL 1000">

Я не могу понять, как это сделать.

(Мое единственное предположение, что, возможно, это как-то связано с XPathNavigator, но я не уверен, что это правильное предположение, и в любом случае, я не совсем понимаю, как правильно его использовать).


Редактировать: проблема решена. Я хочу поблагодарить всех, кто ответил за ваши предложения. Очень ценю!

Ответы [ 4 ]

6 голосов
/ 31 августа 2010

Это действительно неправильный способ работы с XML в .Net.

Вы не упомянули, для какой версии .Net вы разрабатываете.В зависимости от версии изучите использование XmlDocument, XDocument / LINQ to XML.

MSDN в LINQ to XML

MSDN в XmlDocument

2 голосов
/ 31 августа 2010

Вы действительно должны загрузить XML в объект XMlDocument и затем отредактировать его.Но если вы предпочитаете использовать существующий код, этот грязный код должен сработать.

        int indexBegin = source.IndexOf(fullTagBegin) == source.LastIndexOf(fullTagBegin) ? source.IndexOf(fullTagBegin) + fullTagBegin.Length : source.LastIndexOf(fullTagBegin) + fullTagBegin.Length;
        int indexEnd = source.IndexOf(fullTagEnd) == source.LastIndexOf(fullTagEnd) ? source.IndexOf(fullTagEnd) : source.LastIndexOf(fullTagEnd);

Это переместит индексы к последнему появлению любого тега, который вы ищете.Просто замените ваши декларации на эти.

Редактировать: Кроме того, вы используете эти несколько простых строк, чтобы найти / манипулировать вашим XML более понятным способом.

        XmlDocument doc = new XmlDocument();
        doc.Load(filename);
        // or doc.LoadXML(fullXMLcode);

        var elements = doc.GetElementsByTagName("title");
        var element = elements.Item(elements.Count - 1); // returns the last element
        // element.InnerText gets the value you need. You can use this property to change it, too

Надеюсь, это поможет.

1 голос
/ 31 августа 2010

Как уже говорили многие люди, XPath и LINQ подходят друг другу.Вот пример LINQ to XML:

        XDocument doc = XDocument.Load("yourXml.xml");

        var result =
        (from videoInfo in doc.Descendants("videoinfo")
        let quality = videoInfo.Attribute("quality")
        let name = videoInfo.Attribute("name")
        where (quality != null && quality.Value == "1")
                && (name != null && name.Value == "DSL 2000")
        select new 
            {
                Title = videoInfo.Element("title"),
                FileName = videoInfo.Element("filename")
            }
        ).First();

        string title = result.Title.Value;
        string fileName = result.FileName.Value;
1 голос
/ 31 августа 2010

Вам нужно это выражение XPath:

/data/playlist/videoinfo[2]/filename | /data/playlist/videoinfo[2]/title

Или

/data/playlist/videoinfo[2]/*[self::filename or self::title]

Это выражение возвращает набор узлов с элементами filename и title в порядке документа.

В C # (я не эксперт):

XPathDocument doc = new XPathDocument("document.xml"); 

XPathNodeIterator nodeset = doc.CreateNavigator() 
    .Select("/data/playlist/videoinfo[2]/*[self::filename or self::title]"); 

foreach (XPathNavigator node in nodeset) 
{ 
// Your code 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...