1

I have next xml:

<Histories>
  <History>
    <Date>2011.11.11 08:45</Date>
    <Action>Add</Action>
  </History>
  <History>
    <Date>2011.11.12 08:45</Date>
    <Action>Modify</Action>
  </History>
  <History>
    <Date>2011.11.13 08:45</Date>
    <Action>Delete</Action>
  </History>
  <History>
    <Date>2011.11.14 08:45</Date>
    <Action>Add</Action>
  </History>
  <History>
    <Date>2011.11.15 08:45</Date>
    <Action>Modify</Action>
  </History>
  <History>
    <Date>2011.11.16 08:45</Date>
    <Action>Delete</Action>
  </History>
  <History>
    <Date>2011.11.17 08:45</Date>
    <Action>Add</Action>
  </History>
  <History>
    <Date>2011.11.18 08:45</Date>
    <Action>Modify</Action>
  </History>
  <History>
    <Date>2011.11.19 08:45</Date>
    <Action>Delete</Action>
  </History>
  <History>
    <Date>2011.12.20 08:45</Date>
    <Action>Modify</Action>
  </History>
</Histories>

I need to get last node with Action (Add/Modify/Delete). How can I do?

Example:

Add 2011.11.17 08:45

Modify 2011.12.20 08:45

Delete 2011.11.19 08:45

I do: /Histories/History/Action[text()='Add']/../../History[position()=last()] - it do not work.

Thanks

2
  • 1
    Is there a requirement to use Xpath? Could you use LINQ to XMl? Commented Mar 28, 2012 at 5:42
  • Need xpath. I found solution: /Histories/History [Action ='Delete'][last()] /Date Commented Mar 28, 2012 at 6:07

4 Answers 4

1

Use:

/*/History[Action = 'Delete'] [last()]

This selects the last History element that has a child Action with string value "Delete" and that (the History element) is a child of the top element of the XML document.

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

Comments

1
$arr = array('Add','Modify','Delete');
foreach ($arr as $action) {
    $res = $xPath->query('/Histories/History[Action="'.$action.'"][last()]/Date');
    echo "Last $action: " . $res->item(0)->nodeValue . "\n";
}

EDIT: Here's the compact response: /Histories/History[Action="Add"][last()]/Date

4 Comments

ehh, topicstarter has his post tagged .NET and you post a PHP sample?
No, I'm posting the xPath actually. I had the chance to try it in PHP, that's why.
I found solution :) See top ;-)
@RodyvanSambeek Thank you :) I was going to post 3 separate xPath strings but then I thought using a loop instead might give an idea about a more foolproof approach.
0

Consider using linq to XML

Helper method:

string GetValue(XDocument xDocument, string action)
{
    var xElements = xDocument.Descendants("Action").Where(x => x.Value == action);
    var xElement = xElements.Last().Parent;
    return xElement.Element("Date").Value;
}

Usage:

var xml = @"<Histories>
  <History>
    <Date>2011.11.11 08:45</Date>
    <Action>Add</Action>
  </History>
...
  <History>
    <Date>2011.12.20 08:45</Date>
    <Action>Modify</Action>
  </History>
</Histories>";

var xDocument = XDocument.Parse(xml);

var lastAdd= GetLast(xDocument, "Add");
var lastModify = GetLast(xDocument, "Modify");
var lastDelete = GetLast(xDocument, "Delete"); 

string GetLast(XDocument xDocument, string action)
{
    var xElements = xDocument.Descendants("Action").Where(x => x.Value == action);
    var xElement = xElements.Last().Parent;
    return xElement.Element("Date").Value;
} 

Comments

-1
public void insertToDo(string item, string date, string time, string due, string description)
        {
            XElement xEmp = XElement.Load(@"C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");
            //
            xEmp.Add(
                     new XElement("ToDo",
                      new XElement("Item", item),
                       new XElement("date", date),
                        new XElement("time", time),
                        new XElement("due", due),
                        new XElement("description", description))
            );
            xEmp.Save(@"C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");
        }
        public DataSet displayGrid()`enter code here`
        {
            DataSet ds = new DataSet();
            ds.ReadXml("C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");
            return ds;
        }
        public void deleteXml(string item)
        {
            XDocument doc = XDocument.Load("C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");
            doc.Root.Elements("ToDo")
            .Elements("Item")
            .Where(l => l.Value == item)
            .Select(x => x.Parent)
            .Remove();
            doc.Save("C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");
        }
        public void updateTodo(string item, string date, string time, string due, string description)
        {

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");

            foreach (XmlNode node in xmlDoc.SelectNodes("toDoList/ToDo"))
            {
                if (node.SelectSingleNode("Item").InnerText == item)
                {
                    node.SelectSingleNode("Item").InnerText = item;
                    node.SelectSingleNode("date").InnerText = date;
                    node.SelectSingleNode("time").InnerText = time;
                    node.SelectSingleNode("due").InnerText = due;
                    node.SelectSingleNode("description").InnerText = description;

                }

            }
           xmlDoc.Save("C://Users//Khulu//Documents//Visual Studio 2012//Projects//AMD//Schedule//ToDo.xml");
        }

    }
}

1 Comment

What is it? It's answer?

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.