01-12-2017 01:50 PM - edited 03-14-2019 04:56 PM
I know how to do a basic holiday check from an XML file. What I'd like to be able to do is check time of day (TOD) in an XML file. For example if the CSQ is going to be closed for a half day on 12/24/17 I'd like to be able to enter this in my XML file. Below is an example of how I could imagine entering the TOD info in an XML file (but I don't know if this is valid XML). I'm thinking if I could read nested tags in the XML then I could read time values if they're entered for a holiday entry.
<?xml version="1.0" encoding="ISO-8859-1"?>
<Holidays>
<Holiday1>12/24/17</Holiday1>
<todStart>1200</todStart>
<todEnd>1700</todEnd>
<Holiday2>12/25/17</Holiday2>
<Holiday3>12/30/17</Holiday3>
</Holidays>
Solved! Go to Solution.
01-12-2017 04:10 PM
You're pretty close. To nest your todStart and todEnd XML entities inside of Holiday1, it would look like this:
<Holiday1> <todStart>1200</todStart> <todEnd>1700</todEnd> </Holiday1>
However, then you lose the actual date. You cannot just keep it where it was now, you'll need to move it into a child element as well.
<Holiday1>
<date>12/24/17</date>
<todStart>1200</todStart>
<todEnd>1700</todEnd>
</Holiday1>
Then, in your script, you read the child todStart and todEnd after you've made a match on the holiday, and you try and convert (aka cast) them into Time objects.
This is a bit tricky, but one way I do this is like this, where start is a variable of type Time:
Set start = xmldata + " AM"
If you're using 24h format in your XML (E.g., 17:00:00), then the AM, will be ignored. I.e., 0800 AM will work like expected, but 1700 AM will actually be 5:00 PM. The reason to put it in there at all, is that it's required: either AM or PM. And since 0800 PM actuall becomes 8:00 PM, we'll stick with AM.
Now, you need to compare the current time, to see if it's after the new start but before the new end. We can do that with an If step like this:
If (T[now] >= start && T[now] < end) True /* Open */ False /* Close */
You still have quite a bit of work to do in scripting to have the script read this new XML format, so post back if you have more questions. E.g., You date is now in //Holiday1/date
I hope that helps.
01-19-2017 05:43 AM
So how does the end user change the xml file themselves? I haven't seen a process that would allow them to do this without them accessing the actual file. Then you need someone with xml knowledge. I have been using the application side to change the holiday dates, not an xml at all. It does require me to change the dates, but I dont touch the script.
John B.
01-12-2017 04:10 PM
You're pretty close. To nest your todStart and todEnd XML entities inside of Holiday1, it would look like this:
<Holiday1> <todStart>1200</todStart> <todEnd>1700</todEnd> </Holiday1>
However, then you lose the actual date. You cannot just keep it where it was now, you'll need to move it into a child element as well.
<Holiday1>
<date>12/24/17</date>
<todStart>1200</todStart>
<todEnd>1700</todEnd>
</Holiday1>
Then, in your script, you read the child todStart and todEnd after you've made a match on the holiday, and you try and convert (aka cast) them into Time objects.
This is a bit tricky, but one way I do this is like this, where start is a variable of type Time:
Set start = xmldata + " AM"
If you're using 24h format in your XML (E.g., 17:00:00), then the AM, will be ignored. I.e., 0800 AM will work like expected, but 1700 AM will actually be 5:00 PM. The reason to put it in there at all, is that it's required: either AM or PM. And since 0800 PM actuall becomes 8:00 PM, we'll stick with AM.
Now, you need to compare the current time, to see if it's after the new start but before the new end. We can do that with an If step like this:
If (T[now] >= start && T[now] < end) True /* Open */ False /* Close */
You still have quite a bit of work to do in scripting to have the script read this new XML format, so post back if you have more questions. E.g., You date is now in //Holiday1/date
I hope that helps.
01-13-2017 01:30 AM
I've always disagreed with cisco holiday example.
in this example you need to work through holiday1 to holidayN
I always prefer it like below. Then you only make one XML call to see if today is a holiday, doing it like this makes it possible to do holidays several years in advance.
<Holidays>
<Holiday ID="12-24-2017">
<todStart>1200</todStart>
<todEnd>1700</todEnd>
</Holiday>
<Holiday ID="12-25-2017">
<todStart>1200</todStart>
<todEnd>1700</todEnd>
</Holiday>
</Holidays>
If you take it to the next step, you can also create them as <Holiday ID="12-25-any">, it only requires on more xml call, and now you have recurring dates.
/Christian
01-13-2017 07:37 AM
Christian, your reply is also super helpful. I like the idea of of a single XML call and being able to create entries for years further out. I'm just not sure exactly how you make that XML read call when using an ID. Is the "ID" a special XML keyword? Would you show me an example of how to read it?
01-13-2017 08:05 AM
Sure thing,
XML: <Holiday ID="12-24-2017">
Crs editor:"/descendant::Holidays/child::Holiday[attribute::ID='"+sDate+"']/child::todStart"
I can see in my own example I have a D in front: XML: <Holiday ID="D12-24-2017">
Can't recall if it's just for date or if it's needed for correct syntax (ID not starting with a number).
01-18-2017 03:48 PM
Thanks Christian. I ended up with an XML file like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Holidays>
<Holiday Date="1/18/17">
<Active>true</Active>
<StartTime>8:00 AM</StartTime>
<EndTime>8:00 PM</EndTime>
</Holiday>
</Holidays>
Which I can read with either of these "Get XML Document Data" statements:
"/Holidays/Holiday[@Date='1/18/17']/Active"
"/Holidays/Holiday[@Date='" + todaysDate_str + "']/Active"
I return the value of "Active" to a boolean variable I check later to see if it's a holiday. With the second example I set the string variable like this:
todaysDate_str = D[now] (ShortDdate)
01-19-2017 01:32 AM
Looking good :)
and remember the job is never finished.
next could be expanding XML with more info like the prompt to read when a specific holiday is found:
<Holiday Date="1/18/17">
<Active>true</Active>
<StartTime>8:00 AM</StartTime>
<EndTime>8:00 PM</EndTime>
<Prompt>DayOffJan.wav</Prompt>
</Holiday>
01-19-2017 05:38 AM
Good point. I see that I can add whatever data I want later and it won't affect my earlier scripts that reference this XML file, since they simply won't try to call whatever new tags I add.
01-17-2017 07:14 AM
Jim,
Something similar was discussed here: https://supportforums.cisco.com/discussion/13160001/day-week-and-time-day-xml
In that discussion, finding the day of the week was desired. However, using a date instead of the day of week value might work (I haven't tested this). It may require a little modification of your code but it might work. I prefer using the syntax in the discussion rather than the /decendant:: method. For some reason, I can't seem to get that syntax right.
Also in that discussion, was a link to something Anthony Holloway wrote about handling time vaules which was quite helpful. You might find that useful as well.
I hope this helps.
Bill
01-17-2017 07:44 AM
Bill if you prefer that syntax, then just eleminate "Days" from the XPATH all together, since all of your Day elements are in it.
E.g.,
//Day[@ID="1"]/OpenTime
Versus
//Days/Day[@ID="1"/OpenTime
Even simpler!
The only time you would need to also put "Days" in the XPATH, is if you could potentially match the wrong Day element in your XML, but not in your example.
The double slash means "search" essentially, and saying "search" for the root element is kind of pointless, since it's a special elment which cannot be repeated, and therefore not needed to be searched for.
The following would have sufficed, and possibly have been easier on the processing:
/Days/Day[@ID="1"]/OpenTime
;)
01-17-2017 08:29 AM
Thanks for the tip. I always learn something from your posts.
Bill
01-17-2017 10:53 AM
Much appreciated Bill! Take care.
01-13-2017 07:37 AM
Thanks Anthony for the very informative reply, it is very helpful. I do have a few follow up questions though.
I was getting holiday dates like this:
dateFromFile = Get XML Document Data (holidayDoc, "/Holiday/" + holidayIncrement)
So with this new method would my call be like this:
dateStr = Get XML Document Data (holidayDoc, "/Holiday/" + holidayIncrement + "/date/")
todStartStr = Get XML Document Data (holidayDoc, "/Holiday/" + holidayIncrement + "/todStart/")
todEndStr = Get XML Document Data (holidayDoc, "/Holiday/" + holidayIncrement + "/todEnd/")
Would I need include TOD entries for all holidays or would the TOD strings simply get nothing returned to them (in which case I could easily check if the TOD reads were successful)?
As far as the time entry I'm not married to 2400 format. Is it better/easier to use entries like "8:00 AM" and "5:00 PM"?
01-16-2017 09:21 AM
Your modifications look correct.
I would recommend not putting in TOD for all holidays, and just checking for their existence. If they're there, then you'll get the value, if not, then null.
So...
if (xmldata == null || xmldata.trim() == "") True /* TOD Not Found */ False /* TOD Found */
I tend to use 24h format mostly, but I don't see any reason you couldn't use 12h, and specifying the am/pm.
01-18-2017 06:46 PM
I primarily used a combination of Anythony's and Christian's replies to create my solution, but I don't think I can mark more than one post as the correct answer, so I went with Anthony's first reply as the "Correct Answer" post.
Checking for null and "" works to catch missing TOD entries.
I also added two On Exception Goto statements:
One other thing I did slightly different was instead taking the XML time and storing it in a time object I cast the time string to a time object in my if statement like this:
If (T[now] >= T[xmlStart_str] && T[now] < T[xmlEnd_str])
True
/* Open */
False
/* Close */
Thanks to all that replied. I found all the info this this thread very helpful.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide