i'm trying to get the node value in an XML Response. I'm very new to ASP.
Here is the XML:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
<soap:Body>
<ns2:getTextoTsjResponse xmlns:ns2="http://x.com/x/act" xmlns:ns3="http://i.e.com" xmlns:ns4="http://comun.e.com">
<return>
<ns3:texto>
<ns3:datos>
<xop:Include href="cid:888a-4ad6-a511-9c6f0490590e-398#entidad.com" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</ns3:datos>
<ns3:extension>pdf</ns3:extension>
</ns3:texto>
<ns3:textoAnonimizado>
<ns3:datos>
<xop:Include href="cid:888a-4ad6-a511-9c6f0490590e-399#entidad.com" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</ns3:datos>
<ns3:extension>pdf</ns3:extension>
</ns3:textoAnonimizado>
</return>
</ns2:getTextoTsjResponse>
</soap:Body>
</soap:Envelope>
I succeded geting the XMLDoc and parse. What im trying to do then is get href values within node.
Here is the ASP code.
'Response from server with the XML
xmlParseado = response.Text
Set xmlDoc = Server.CreateObject("MSXML2.DOMDocument")
xmlDoc.loadXML(xmlParseado)
if xmlDoc.parseError.errorcode <> 0 then
Response.Write("XML Error...<br>")
else
Call xmlDoc.setProperty("SelectionLanguage", "XPath")
Call xmlDoc.setProperty("SelectionNamespaces", "xmlns:ns3")
Dim node
'Here im trying to get href value from <ns3:datos> node.
Set node = xmlDoc.selectSingleNode("//ns3:texto//ns3:datos//*")
If (node Is Nothing) Then
Response.write "nothing"
Else
response.write(TypeName(node) & "<br />")
End If
end if
Some help would be apreciated.
Thanks in advance
You are really close.
Sadly your XML (like many poorly designed XML documents) suffers from namespace overkill. If you think of elements like data files on a file system, these XML designers are paranoid that two files (elements) will have the same name, so they put every file (element) on a separate disk instead of just using folders (nesting elements) for context. In my entire career, I've never run into an issue with two files having the same name, but every day, there's a post on Stackoverflow from someone having trouble with namespaces.
So think of namespaces like a separate disk in a filesystem. The document specifies each "disk" with a nick name (the prefix like ns3), and a location (the URI like http://i.e.com). Now when you're querying XML with XPath, have to tell the parser about all of the namespaces (disks), and you specify the prefix in front of every element on the "disk". You're XPath will look like "//ns3:datos", not just "//datos".
So armed with namespaces, they became the "solution" for everything. When SOAP was created, the designers went crazy with namespaces, and as a result, everyone put namespaces in everything. The designers of SOAP must have been worried that their Header, Envelope and Body element names would be re-used in SOAP message data. Instead of naming the elements "SOAP_Header", "SOAP_Envelope", and "SOAP_Body" that everyone could remember, they implemented SOAP with XML namespaces just in case the message content accidentally also included an element named "Header", "Envelope" or "Body".
When you set the SelectionNamesSpaces, you need to set both the prefix and the URI. In this example I have all the namespaces in your document.
Good luck with your project, and please join me in killing namespaces where ever possible :)
if xmlDoc.parseError.errorcode <> 0 then
Response.Write("XML Error...<br>")
' NOTE: Avoid nesting else statements, just stop.
Response.End
End If
Call xmlDoc.setProperty("SelectionLanguage", "XPath")
' NOTE: you're missing the URI here in your namespace http://i.e.com
' Call xmlDoc.setProperty("SelectionNamespaces", "xmlns:ns3")
' Add all of the namespaces, including the prefix and URI
Call xmlDoc.setProperty("SelectionNamespaces", "xmlns:xop='http://www.w3.org/2004/08/xop/include' xmlns:ns2='http://x.com/x/act' xmlns:ns3='http://i.e.com' xmlns:ns4='http://comun.e.com'")
'Here im trying to get href value from <ns3:datos> node.
Dim node
Set node = xmlDoc.selectSingleNode("//ns3:texto//ns3:datos//xop:Include")
If (node Is Nothing) Then
Response.write "nothing"
Else
Response.write( node.getAttribute( "href" ) )
End If
' Here's how to get all of the Includes
Dim ndList
set ndList = xmlDoc.selectNodes( "//xop:Include" )
for each ndInclude in ndList
Response.write( ndInclude.getAttribute( "href" ) )
next
Related
So, as I figured out, when I have a form with enctype="multipart/form-data" and I upload a file, I can no longer access the object request. The following error is shown:
Cannot use the generic Request collection after calling BinaryRead.
After checking some resources, I stumpled upon a statement, which says: "This is by design". Well, okay, not here to judge about design-decisions.
To give you a quick overview, let me walk you through the code:
if request("todo") = "add" then
Set Form = New ASPForm
category = request("category")
title = request("title")
if len(Form("upload_file").FileName) > 0 then
filename = Form("upload_file").FileName
DestinationPath = Server.mapPath("personal/allrounder/dokumente/")
Form.Files.Save DestinationPath
end if
end if
Nothing too special here so far. Later however, when I try to access my request object, the error mentioned above occures:
<% if request("todo") = "new" then %>
...
My question now, how to get rid of it or fix this. I don't want to open the upload in a popup if there is another way around. This is the only solution I could think off.
Perfectly would be an object, which checks Form and request. Alternatively maybe a check at the top of the file, which object I have to use?
Thanks for any suggestions.
There used to be a very popular ASP class/component that solved ASP file uploads. The site for that component has been taken down, but the code is mirrored here:
https://github.com/romuloalves/free-asp-upload
You can include this ASP page on your own page, and on your page instantiate the class to get access to the files in your form, but also to the form variables. Here is a piece of example code (Upload.Form accesses the form fields):
Dim uploadsDir : uploadsDir = server.mapPath(".") ' whatever you want
Dim Upload, ks, fileKey, mailto
Set Upload = New FreeASPUpload
call Upload.Save(uploadsDir)
ks = Upload.UploadedFiles.keys
for each fileKey in ks
Response.write(fileKey & " : " & Upload.UploadedFiles(fileKey).FileName & "<br/>")
next
mailto = Upload.form("mailTo")
Set Upload = Nothing
If you want to stick to your own implementation, you can probably figure out how to get to the form variables in a multipart/form-data encoded data stream by having a look at the code they use to do so.
I've .NET webservice, which takes a encoded html-string as a parameter, decodes the string and creates a PDF from the html. I want to make a synchronous server side call to the webservice from a classic asp webpage. It works fine if use a plain text string (with no html tags), but when I send a encoded html string the webservice it seems that the string is empty when it reaches the webservice.
The webservice is working fine when I call it from client side, with both plain text string and an encoded html string.
My code looks like this:
Private Sub SaveBookHtmlToPdf(pHtml, pShopId)
Set oXMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0")
Dim strEnvelope
strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Server.HTMLEncode(pHtml)
Call oXMLHTTP.Open("POST", "https://mydomain.dk:4430/PdfWebservice.asmx/SaveBookToPdf", false)
Call oXMLHTTP.SetRequestHeader("Content-Type","application/x-www-form-urlencoded")
Call oXMLHTTP.Send(strEnvelope)
Set oXMLHTTP = Nothing
End Sub
It smells like some kind of security issue on the server. It's working when posting a asynchronous call from the client side, but not when it comes from server side - it seems that the encoded html string is somehow not allowed in a server side call to the webservice.
Anyone who know how to solve this tricky problem?
This looks all wrong to me:
Server.HTMLEncode(pHtml)
Its quite common for developers to get confused between HTML encoding and URL encoding even though they are quite different. You are posting data that needs to be URL encoded. Hence your code should use URLEncode instead:
strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Server.URLEncode(pHtml)
Edit:
One thing that URLEncode does that may not be compatible with a URLEncoded post is it converts space to "+" instead of "%20". Hence a more robust approach might be:
strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Replace(Server.URLEncode(pHtml), "+", "%20")
Another issue to watch out for is that the current value of Response.CodePage will influence how the URLEncode encodes non-ASCII characters. Typically .NET does things by default in UTF-8. Hence you will also want to make sure that your Response.CodePage is set to 65001.
Response.CodePage = 65001
strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Replace(Server.URLEncode(pHtml), "+", "%20")
This may or may not help but I use a handy SOAP Class for Classic ASP which solved a few problems I was having doing it manually. Your code would be something like this:
Set cSOAP = new SOAP
cSOAP.SOAP_StartRequest "https://mydomain.dk:4430/PdfWebservice.asmx", "", "SaveBookToPdf"
cSOAP.SOAP_AddParameter "pShopId", pShopId
cSOAP.SOAP_AddParameter "pEncodedHtml", Server.HTMLEncode(pHtml)
cSOAP.SOAP_SendRequest
' result = cSOAP.SOAP_GetResult("result")
You will probably need to set your namespace for it to work ("" currently), and uncomment the 'on error resume next' lines from the class to show errors.
AnthonyWJones made the point about URL encoding and HTML encoding, and the original problem being experienced is likely a combine of the two, a race condition if you will. While is was considered answered, it partially wasn't, and hopefully this answers the cause of the effect.
So, as the message get HTMLEncoded, the html entities for the tags become such '<' = '<'.
And as you may know, in URLEncoding, &'s delimit parameters; thus the first part of this data strEnvelope = "pShopId=" & pShopId & "&pEncodedHtml=" & Server.HTMLEncode(pHtml) upto the "&pEncodedHtml" bit, is fine. But then "<HTML>..." is added as the message, with unencoded &'s...and the receiving server likely is delimiting on them and basically truncating "&pEncodedHtml=" as a null assign: "&pEncodedHtml=<HTML>... ." The delimiting would be done on all &'s found in the URL.
So, as far as the server is concerned, the data for parameter &pEncodedHtml was null, and following it were now several other parameters that were considered cruft, that it likely ignored, which just happened to actually be your message.
Hope this provides additional info on issues of its like, and how to correct.
I am having some difficulty with an xPath expression.
Context: I am using an XML document to store queries / stored procedure names in an ASP application. I use a utility function to load the xmldocument (if it isn't previously loaded) and I am attempting to select the node set from the document that matches an Id element. Here is my Xml document:
<Queries>
<Id>USER001
<Sql>spUsers_GetUserByUserName</Sql>
</Id >
<Id <USER002
<Sql>spUsers_GetUserByEmail</Sql>
</Queries>
Here is the code (I am using VB.NET)
Module Utility
private sqlXml as xmldocument
'....other stuff.....
Public Function GetSql(queryId as string) as string
dim qry as string
dim node as XmlNode
if sqlXml is nothing then
sqlXml = new xmldocument
sqlXml.Load (..path)
end if
qry = "//Id['" & queryId & "']" 'xPath to select the Id node = to paramter passed
node = sqlxml.SelectSingleNode(qry) 'set node <Id><Sql></Sql></Id>
return node.SelectSingleNode("//Sql").InnerText 'Return the Sql element value from the Id
End Function
The Problem:
the node variable only returns the first element. I have verified the that the qry string that is used to SelectSingleNode IS the correct Id value (i.e. USER002) - however the node is getting loaded with the USER001 element. It is obviously the xPath expression that is messed up. What do I need to tweak on the xPath expression so that I can return the correct <Id> element and corresponding child <Sql> element.
Any help would be appreciated.
Google XML COOKTOP and install it. It's a great little freeware app for trying out XPATH and XSLT expressions on XML data files and seeing the results.
It looks like you're trying to to construct an expression like //Id['USER002']. That will select all the E elements for which the effective boolean value of 'USER002' is true - which is all of them. It's not clear what you intended because your XML sample is a mess, but it should be something like //Id[#id='USER002']
Also, you really shouldn't be constructing XPath expressions by string concatenation. It leaves you prone to injection attacks and to accidental misfunctioning when someone supplies a string containing quotes. It's also inefficient. Construct a string containing a variable reference $param, and set the parameter from the API. (Don't know how to do that in VB, I'm afraid).
I'm breaking my head over this for a while now and I have no clue what I do wrong.
The scenario is as followed, I'm using swfupload to upload files with a progressbar
via a webservice. the webservice needs to return the name of the generated thumbnail.
This all goes well and though i prefer to get the returned data in json (might change it later in the swfupload js files) the default xml data is fine too.
So when an upload completes the webservice returns the following xml as expected (note I removed the namespace in webservice):
<?xml version="1.0" encoding="utf-8"?>
<string>myfile.jpg</string>
Now I want to parse this result with jquery and thought the following would do it:
var xml = response;
alert($(xml).find("string").text());
But I cannot get the string value. I've tried lots of combinations (.html(), .innerhtml(), response.find("string").text() but nothing seems to work. This is my first time trying to parse xml via jquery so maybe I'm doing something fundemantally wrong. The 'response' is populated with the xml.
I hope someone can help me with this.
Thanks for your time.
Kind regards,
Mark
I think $(xml) is looking for a dom object with a selector that matches the string value of XML, so I guess it's coming back null or empty?
The First Plugin mentioned below xmldom looks pretty good, but if your returned XML really is as simply as your example above, a bit of string parsing might be quicker, something like:
var start = xml.indexOf('<string>') + 8;
var end = xml.indexOf('</string>');
var resultstring = xml.substring(start, end);
From this answer to this question: How to query an XML string via DOM in jQuery
Quote:
There are a 2 ways to approach this.
Convert the XML string to DOM, parse it using this plugin or follow this tutorial
Convert the XML to JSON using this plugin.
jQuery cannot parse XML. If you pass a string full of XML content into the $ function it will typically try to parse it as HTML instead using standard innerHTML. If you really need to parse a string full of XML you will need browser-specific and not-globally-supported methods like new DOMParser and the XMLDOM ActiveXObject, or a plugin that wraps them.
But you almost never need to do this, since an XMLHttpRequest should return a fully-parsed XML DOM in the responseXML property. If your web service is correctly setting a Content-Type response header to tell the browser that what's coming back is XML, then the data argument to your callback function should be an XML Document object and not a string. In that case you should be able to use your example with find() and text() without problems.
If the server-side does not return an XML Content-Type header and you're unable to fix that, you can pass the option type: 'xml' in the ajax settings as an override.
I'm maintaining a Classic ASP app written in VB Script by an outside company long, long ago.
I have an array of imagefile paths, like so:
dim banners, arrKeys, i
set banners=CreateObject("Scripting.Dictionary")
banners.Add "banner1.jpg", "http://www.somelink.com"
banners.Add "banner2.jpg", "http://www.somelink.com"
banners.Add "banner3.jpg", "http://www.somelink.com"
This will exist ONLY on pages that have banner ads. There is some standard code that iterates through this list in an include file (common to all pages).
If Not banners Is Nothing then
' then loop through the Dictionary and make a list of image links
End if
The problem is that if banners is not instantiated on the page (it's not on all pages), I get a Can't find object error
What's the proper way to check if an object exists in VB Script?
#Atømix: Replace
If Not banners Is Nothing then
and use
If IsObject(banners) Then
Your other code you can then place into an include file and use it at the top of your pages to avoid unnecessary duplication.
#Cheran S: I tested my snippets above with Option Explicit on/off and didn't encounter errors for either version, regardless of whether Dim banners was there or not. :-)
IsObject could work, but IsEmpty might be a better option - it is specifically intended to check if a variable exists or has been initialised.
To summarize:
IsEmpty(var) will test if a variable exists (without Object Explicit), or is initialised
IsNull(var) will test if a variable has been assigned to Null
var Is Nothing will test if a variable has been Set to Nothing, but will throw an error if you try it on something that isn't an object
IsObject(var) will test if a variable is an object (and will apparently still return False if var is Empty).
If a variable is declared, but not initialized, its value will be Empty, which you can check for with the IsEmpty() function:
Dim banners
If IsEmpty(banners) Then
Response.Write "Yes"
Else
Response.Write "No"
End If
' Should result in "Yes" being written
banners will only be equal to Nothing if you explicitly assign it that value with Set banners = Nothing.
You will have problems, though, with this technique if you have Option Explicit turned on (which is the recommendation, but isn't always the case). In that case, if banners hasn't been Dimed and you try to test IsEmpty(banners), you will get a runtime error. If you don't have Option Explicit on, you shouldn't have any problems.
edit: I just saw this related question and answer which might help, too.
Somewhat related is IsMissing() to test if an optional parameter was passed, in this case an object, like this:
Sub FooBar(Optional oDoc As Object)
'if parameter is missing then simulate it
If IsMissing(oDoc) Then Dim oDoc as Object: oDoc = something
...
You need to have at least dim banners on every page.
Don't you have a head.asp or something included on every page?
Neither of IsEmpty, Is Object, IsNull work with the "Option Explicit" Setting, as stealthyninja above has misleadingly answered.
The single way i know is to 'hack' the 'Option Explicit' with the 'On Error Resume Next' setting, as Tristan Havelick nicely does it here:
Is there any way to check to see if a VBScript function is defined?