cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2130
Views
54
Helpful
25
Replies

UCCX check time of day (TOD) from XML file

jim-j
Level 3
Level 3

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>
2 Accepted Solutions

Accepted Solutions

Anthony Holloway
Cisco Employee
Cisco Employee

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.

View solution in original post

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.

View solution in original post

25 Replies 25

Anthony Holloway
Cisco Employee
Cisco Employee

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.

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

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?

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

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)

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>

 

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.

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

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

;)

Thanks for the tip. I always learn something from your posts.

Bill

Much appreciated Bill!  Take care.

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"?

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.

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:

  1. ExpressionException catches time formatting issues like 8:00AM (with no space before the AM)
  2. DocumentException catches general XML formatting issues (like forgetting a closing tag)

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.

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: