0

I’ve got a problem witch I’ve been trying to solve almost for a week now, but it seems that, unfortunately, I can’t manage it by myself. Maybe somebody could help me.

I’ve got this type of source 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>

And here are parts of the code that let me get required tag content from xml page above:

        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]","_");

The problem is:

everything works fine except the fact, that there are two "filename" and "title" tags in the source xml, but I need to choose only second ones, those that are under this line:

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

and somehow skip/ignore first ones, those that are above previous line and right under this line:

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

I can't figure out how to do that.

(My only guess is that maybe it has something to do with XPathNavigator, but I’m not sure if that’s a right guess, and anyway, I don’t really understand how to use it properly).


Edit: problem solved. I want to thank everyone who replied for your suggestions. Really appreciated!

1
  • 6
    Regex and string replace are usually not the right way to change an XML file. Use a standard, fast, well-tested library instead. Linq to XML can do some magic as well, perhaps. You are attempting a poor re-write of a solid library created by dozens of experienced professionals (coders, testers, etc). Commented Aug 30, 2010 at 22:45

4 Answers 4

6

This is really not the right way to go about working with XML in .Net.

You didn't mention which version of .Net you are developing for. Depending on the version look into using XmlDocument, XDocument / LINQ to XML.

MSDN on LINQ to XML

MSDN on XmlDocument

Sign up to request clarification or add additional context in comments.

1 Comment

Absolutely agree. Cannot overstate how much work you're creating for yourself by doing it this way.
2

You should really load the XML into XMlDocument object and then edit it. But if you prefer to use your existing code, this dirty code should do the trick.

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

This will move the indexes to the last occurrence of whatever tag you're looking for. Just replace your declarations with this ones.

Edit: Additionally, you use this easy few lines to find/manipulate your XML in a much cleaner way.

        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

Hope this helps.

1 Comment

Thank you, thank you so much! It really helps, this “dirty code” works like a charm. Yes, I got that I should work with XML another way, but right now I really prefer to change as little as possible, because I’ve just discovered one more thing in the code that must be fixed and I have to concentrate on it. Thanks again for your help.
1

You need this XPath expression:

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

Or

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

These expression return a node set with filename and title element in document order.

In C# (I'm not an expert):

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 
} 

Comments

1

As many people have already said, XPath and LINQ are both suitable. Here's LINQ to XML sample:

        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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.