drmohundro/SWXMLHash and escaping values in Swift - swift

I have working on a project that handles xml responses. After a search I found a library on github drmohundro/SWXMLHash that works inspired on the "Swifty JSON". After a while using it, I have realised that I can't get values with escaping values.
The xml response looks like
let xmlResponseString = "<TrackList><Entry><Id>2</Id><Uri>/Input/E21u</Uri><Metadata><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="E21"><dc:title>Doing It To Death</dc:title><upnp:album>Ash & Ice</upnp:album><upnp:artist>The Kills</upnp:artist><upnp:class>object.item.audioItem.musicTrack</upnp:class><upnp:albumArtURI>http://192.168.1.106:8088/storage/emulated/0/record_cache/album_art/1535461905688.jpg</upnp:albumArtURI><res sampleFrequency="96000" bitsPerSample="24" bitrate="2304000" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg" duration="00:04:07.431">/Input/E21</res></item></DIDL-Lite></Metadata></Entry></TrackList>"
In the response the album name is equal to "Ash & Ice". However the value returned is "Ash "
That is how I get the value:
let xmlHash = SWXMLHash.parse(xmlResponseString)
albumName = xmlHash["DIDL-Lite"]["item"]["upnp:album"].element?.text
Furthermore, inspecting "xmlHash" it looks like the error already comes from "SWXMLHash.parse(xmlResponseString)".
Does the "xmlResponseString" need to be escaped?
Is it something that the library doesn't handle properly?
Any alternative?
Thank you
EDIT
The response comes from another OpenHome provider device.
The original response is:
<TrackList>
<Entry>
<Id>2</Id>
<Uri>/Input/E21u</Uri>
<Metadata><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="E21"><dc:title>Doing It To Death</dc:title><upnp:album>Ash & Ice</upnp:album><upnp:artist>The Kills</upnp:artist><upnp:class>object.item.audioItem.musicTrack</upnp:class><upnp:albumArtURI>http://192.168.1.106:8088/storage/emulated/0/record_cache/album_art/1535461905688.jpg</upnp:albumArtURI><res sampleFrequency="96000" bitsPerSample="24" bitrate="2304000" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg" duration="00:04:07.431">/Input/E21</res></item></DIDL-Lite>
</Metadata>
</Entry>
According to the developer, the Metadata value has been escaped because it is an XML inside an XML. Not sure if that matter
Since I want to create an universal parse function to populate a class, I have created this method:
func unescapeXMLPredefinedCharacters(value:String?) -> String{
var audioString = ""
if value != nil{
audioString = value!
//Replace Unicode HTML Entity
audioString = audioString.replacingOccurrences(of: """, with: "\"")
audioString = audioString.replacingOccurrences(of: "&", with: "&")
audioString = audioString.replacingOccurrences(of: "&apos;", with: "'")
audioString = audioString.replacingOccurrences(of: "<", with: "<")
audioString = audioString.replacingOccurrences(of: ">", with: ">")
//Replace Unicode Decimal
audioString = audioString.replacingOccurrences(of: """, with: "\"")
audioString = audioString.replacingOccurrences(of: "&", with: "&")
audioString = audioString.replacingOccurrences(of: "'", with: "'")
audioString = audioString.replacingOccurrences(of: "<", with: "<")
audioString = audioString.replacingOccurrences(of: ">", with: ">")
//Replace Unicode Hex
audioString = audioString.replacingOccurrences(of: """, with: "\"")
audioString = audioString.replacingOccurrences(of: "&", with: "&")
audioString = audioString.replacingOccurrences(of: "'", with: "'")
audioString = audioString.replacingOccurrences(of: "<", with: "<")
audioString = audioString.replacingOccurrences(of: ">", with: ">")
}
return audioString
}
It doesn't know which unicode type has been used for the unescaping.
Then I get the answer from my original question

The problem is that the escaped inner xml already is wrong in a sense that it contains & characters (in unicode), and maybe < and others.
First, you should not unescape unicode entities like & or < at all, because the XmlParser handles this for you.
Then, you should unescape unicode entities like & etc. into xml entities like & (rather than to &), which then the xml parser will handle (see above)

According to Andreas Answer, I have change the function
func unescapeXMLPredefinedCharacters(value:String?) -> String{
var audioString = ""
if value != nil{
audioString = value!
//Replace Unicode Decimal
audioString = audioString.replacingOccurrences(of: """, with: """)
audioString = audioString.replacingOccurrences(of: "&", with: "&")
audioString = audioString.replacingOccurrences(of: "'", with: "&apos;")
audioString = audioString.replacingOccurrences(of: "<", with: "<")
audioString = audioString.replacingOccurrences(of: ">", with: ">")
}
return audioString
}

Related

error when try to print two values

In the official swift document it says
"The print(_:separator:terminator:) function is a global function that prints one or more values to an appropriate output."
var welcomeMessage = "Hello"
var friendlyWelcom = "Hello!"
print(friendlyWelcom, separator: ",", terminator: "", welcomeMessage, separator: ",", terminator: "") // Why this is not working
Question As the comments inside the code - why do print(friendlyWelcom, welcomeMessage) and print(friendlyWelcom, separator: ",", terminator: "" work but print(friendlyWelcom, separator: ",", terminator: "", welcomeMessage, separator: ",", terminator: "") generates a compiler error?
You cannot simply add named parameters as you wish. Instead you should pass the variables to print in comma seperated as the first argument. They then get joined with the separator in between and the terminator at the end:
print(friendlyWelcom, welcomeMessage, separator: " - ", terminator: "?")
Outputs
Hello! - Hello?
You can add as many variables there as you wish:
print(friendlyWelcom, welcomeMessage, 123, "somethingElse", "etc", separator: " - ", terminator: "!!!!")
Hello! - Hello - 123 - somethingElse - etc!!!!

Pydev Program Continually Terminating

I am fairly new programmer, currently I have been assigned a project to create a looping calculator that even after you use one of the calculator functions it will keep going until you make a selection provided. My problem with my calculator currently is that there is an incessant termination whenever I try to test my function on Pydev. I already fixed the first problem where Pydev read one of my variables (choice) as unused so I used the "ctrl + 1" trick and that got rid of the unused variable warning. Any tips on how I might be able to run this program and have it continually loop?
def main():
loop=1
choice=0 # #UnusedVariable
while loop == 1:
print("Welcome to Calculator Function!")
print("Your options are:")
print(" ")
print("1/) Addition")
print("2/) Subtraction")
print("3/) Multiplication")
print("4/) Division")
print("5/) Quit CalculatorFunction.py")
print(" ")
choice = int(raw_input("Choose your option: ").strip())
if choice == 1:
add1 = input("Add what: ")
add2 = input("To what: ")
print add1, "+", add2, "=", add1+add2
elif choice == 2:
sub2 = input("Subtract what: ")
sub1 = input("From what: ")
print sub1, "-", sub2, "=", sub1-sub2
elif choice == 3:
mult1 = input("Multiply what: ")
mult2 = input("To what: ")
print mult1, "*", mult2, "=", mult1*mult2
elif choice == 4:
div2= input("Divide what: ")
div1= input("From what: ")
print div1, "/", div2, "=", div1/div2
elif choice == 5:
loop = 0
print"Thank you for using CalculatorFunction.py have a good day!"
else:
print"No selection made, please try again."
if __name__ == '__main__':
main()
Your if - else block is outside the while loop, that is why it doesn't work. Here's the properly indented code:
def main():
loop=1
choice=0 # #UnusedVariable
while loop == 1:
print("Welcome to Calculator Function!")
print("Your options are:")
print(" ")
print("1/) Addition")
print("2/) Subtraction")
print("3/) Multiplication")
print("4/) Division")
print("5/) Quit CalculatorFunction.py")
print(" ")
choice = int(raw_input("Choose your option: ").strip())
if choice == 1:
add1 = input("Add what: ")
add2 = input("To what: ")
print add1, "+", add2, "=", add1+add2
elif choice == 2:
sub2 = input("Subtract what: ")
sub1 = input("From what: ")
print sub1, "-", sub2, "=", sub1-sub2
elif choice == 3:
mult1 = input("Multiply what: ")
mult2 = input("To what: ")
print mult1, "*", mult2, "=", mult1*mult2
elif choice == 4:
div2= input("Divide what: ")
div1= input("From what: ")
print div1, "/", div2, "=", div1/div2
elif choice == 5:
loop = 0
print"Thank you for using CalculatorFunction.py have a good day!"
else:
print"No selection made, please try again."
if __name__ == '__main__':
main()
This worked well on pydev.
Thanks to your tips on "indentation" and a couple of other things I finally figured out the program works thank you all for your input. What I did to fix my immediate termination was fix the indentation. Then to make it so the program continually loops if a selection isn't made I added the continue, in essence the only way to terminate the program is to select the option quit which is listed as "5".
def main()
loop=1
choice=0 # #UnusedVariable
while loop == 1:
print(" ")
print("Welcome to Calculator Function!")
print("Your options are:")
print(" ")
print("1) Addition")
print("2) Subtraction")
print("3) Multiplication")
print("4) Division")
print("5) Quit CalculatorFunction.py")
print(" ")
choice = int(raw_input("Choose your option: ").strip())
if choice == 1:
add1 = int(raw_input("Add what: "))
add2 = int(raw_input("To what: "))
print add1, "+", add2, "=", add1+add2
elif choice == 2:
sub2 = int(raw_input("Subtract what: "))
sub1 = int(raw_input("From what: "))
print sub1, "-", sub2, "=", sub1-sub2
elif choice == 3:
mult1 = int(raw_input("Multiply what: "))
mult2 = int(raw_input("To what: "))
print mult1, "*", mult2, "=", mult1*mult2
elif choice == 4:
div2= int(raw_input("Divide what: "))
div1= int(raw_input("From what: "))
print div1, "/", div2, "=", div1/div2
elif choice == 5:
loop = 0 #Ends the program
print"Thank you for using CalculatorFunction.py have a good day!"
else:
print"No selection made, please try again."
continue #loops the program
if name == 'main':
main()

key value relation on Skip List (DXL/DOORS)

I am trying to find the same login id users in database.
First I put every user to skiplist then I want to compare one by one. My question is how can i get the key value on Skiplist.
The piece of my code is here :
for lUser in userList do {
string uName = lUser.name
string uEmail = lUser.email
string uSys = lUser.systemLoginName
string uAdr = lUser.address
outBuf += uName sep uSys sep uEmail sep uAdr
outBuf += "\n"
// Here I have to add some code, I can put the values but not get again or compare
// I need some for loop and get every key value
put(skiplist,count,uSys)
print count
print "\n"
count++
}
Could someone give tips for this, I am new on this language. Thanks in advance.
EDIT: NOW IT IS WORKING
pragma runLim,0
string sep = ";"
string dbName = getDatabaseName
print "\n" "List of doors user in database " getDatabaseName ": \n\n"
int count = 0
User lUser
Group lGroup
Skip skiplist = create
for lUser in userList do {
string uName = lUser.name
string uEmail = lUser.email
string uSys = lUser.systemLoginName
string uAdr = lUser.address
if(null uSys)
{
print uName " doesn't have a System Name.\n"
} else {
bool flagDuplicate = false
string nameDuplicate = ""
string s = ""
for s in skiplist do {
if(s == uSys) {
flagDuplicate = true
nameDuplicate = (string key skiplist)
break
}
}
if(flagDuplicate) print "Users '" uName "' and '" nameDuplicate "' have the same System Name (" uSys ").\n"
else put(skiplist,uName,uSys)
}
}
pragma runLim,0 this line is for avoiding the execution time warning.
It sounds like what you are looking for is this:
for lUser in userList do {
string uName = lUser.name
string uEmail = lUser.email
string uSys = lUser.systemLoginName
string uAdr = lUser.address
outBuf += uName sep uSys sep uEmail sep uAdr
outBuf += "\n"
if(null uSys)
{
print uName " doesn't have a System Name.\n"
} else {
bool flagDuplicate = false
string nameDuplicate = ""
string s = ""
for s in skiplist do {
if(s == uSys) {
flagDuplicate = true
nameDuplicate = (string key skiplist)
break
}
}
if(flagDuplicate) print "Users '" uName "' and '" nameDuplicate "' have the same System Name (" uSys ")."
else put(skiplist,uName,uSys)
print "\n"
}
}
EDIT: I added a check for a blank uSys, you can do anything you want there, if you want to just add all the empty ones to a list then print it out at the end that would work too.
This should at least point you in the right direction.
NOTE: I don't have the ability to test this code currently so I apologize if there are any errors or typos. But I think it will get you close enough.
Good luck!

Return value and if expression

I have the following code to get a row from SQL database. It returns either a record or None. However, it doesn't return because getLogin has the type of unit = () and there is a warning
warning FS0020: This expression should have type 'unit', but has type 'login option'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name.
How to resolve the issue? Is it the best way to handle Ado.Net?
type login = { userName: string; password: string; downloadDir: string}
let getLogin =
let conn = new SqlConnection("Data Source=......;Integrated Security=SSPI;")
try
conn.Open()
let cmd = new SqlCommand("select * FROM Login where website = 'xxx'", conn)
cmd.CommandType <- CommandType.Text
use reader = cmd.ExecuteReader()
if (reader.HasRows) then (
reader.Read() |> ignore
let userName = reader.GetString(5)
let password = reader.GetString(6)
printfn "%s" userName
Some { userName = userName; password = password; downloadDir = "zzz" }
)
else (
printfn "Cannot find login information."
None
)
conn.Close()
with
| :? System.Data.SqlClient.SqlException as sqlEx -> printfn "%A" sqlEx.Message
| _ -> printfn "Unknown Exception"
Update:
I've updated the code by Thomas' suggestion.
let getLogin =
use conn = new SqlConnection("Data Source=mdyptcafgprd101;Initial Catalog=App;Integrated Security=SSPI;")
try
conn.Open()
let cmd = new SqlCommand("select * FROM app.WebCrawler.LoginLbl where website = 'CTSLink'", conn)
cmd.CommandType <- CommandType.Text
use reader = cmd.ExecuteReader()
if (reader.HasRows) then (
reader.Read() |> ignore
let userName = reader.GetString(5)
let password = reader.GetString(6)
Some { userName = userName; password = password; downloadDir = "zzz" }
)
else (
printfn "Cannot find login information."
None
)
with
| :? System.Data.SqlClient.SqlException as sqlEx -> printfn "%A" sqlEx.Message
| _ -> printfn "Unknown Exception"
However, now it gets the following error on line | :? System....
s.fs(31,69): error FS0001: Type mismatch. Expecting a
'a -> login option
but given a
'a -> unit
The type 'login option' does not match the type 'unit'
>
The problem is that your if expression is followed by another line:
if reader.HasRows then
(...)
else
(...)
conn.Close()
... and so the compiler thinks that you are ignoring the result of if and instead returning the result of the last expression, which is conn.Close().
The easiest way to fix this is to use the use construct - it automatically disposes of the conn value when it comes out of scope, and so you do not need the last line and can just use if as the last expression in your code:
use conn = (...)
if reader.HasRows then
(...)
else
(...)
Also, you'll need to return some result in the with ... branch - that handles an exception and you either need to raise another exception or return a valid value - in this case, probably None.

PHP Remove All Non-alphanumeric Characters Except Apostrophes

$keywords = explode("\n",$_POST['keywords']);
//Inserting into Database
foreach($keywords as $key => $keyword){
$keyword = strtolower(trim($keyword));
$keyword = preg_replace("/[^A-Za-z0-9' ]/", "", $keyword);
$keyword = preg_replace("/\s+/", " ", $keyword);
$insertkeywords = "INSERT IGNORE INTO kwdb (keyword) VALUES ('$keyword')";
mysql_query($insertkeywords);
}
I can't for the life of me figure out why this code won't insert the keywords into the database when I have an apostrophe in the:
"/[^A-Za-z0-9' ]/"
But when I remove it to be:
"/[^A-Za-z0-9 ]/"
This script inserts records into the database.
What am I trying to do?
I have a textarea on a form. For each keyword on a new line, I explode based on the \n. I want to remove all non-letter and non-number characters from the keywords but don't want apostrophes to be removed.
I basically want all keywords to be lower-case with leading, trailing and extra white spaces - 2 or more blank spaces trimmed down to one - removed along with any non-letter and non-number characters except for apostrophes.
You need to escape your keyword: $insertkeywords = "INSERT IGNORE INTO kwdb (keyword) VALUES ('".mysql_real_escape_string($keyword)."')";
Thank you clover. Without your help, it would have taken me many hours to figure that one out! I ended up using mysqli_real_escape_string instead of mysql_real_escape_string because mysql_real_escape_string says it is deprecated as of PHP 5.5.0. As a result, I had to change it up a bit but the below code seems to work great for me so far (in case anyone else runs across this).
$con = mysqli_connect("localhost","username","password");
if (!$con)
{
die('Could not connect: ' . mysqli_error());
}
else
{
echo "Connected Successfully!";
}
//select database
mysqli_select_db($con, "test");
$keywords = explode("\n",$_POST['keywords']);
//Inserting into Database
foreach($keywords as $key => $keyword){
$keyword = preg_replace("/[^A-Za-z0-9' ]/", " ", $keyword);
$keyword = preg_replace("/\s+/", " ", $keyword);
$keyword = strtolower(trim($keyword));
//$insertkeywords = "INSERT IGNORE INTO kwdb (keyword) VALUES ('$keyword')";
$insertkeywords = "INSERT IGNORE INTO kwdb (keyword) VALUES ('".mysqli_real_escape_string($con, $keyword)."')";
mysqli_query($con, $insertkeywords);
}