I'm trying to parse a simple XML file in my j2me application. But the parsing fails:
XML File
<companies>
<company CompanyId="6">
<CompanyName>Test Company 1</CompanyName>
<SapNumber>0</SapNumber>
<RootCompanyId>1</RootCompanyId>
<ParentCompanyId /> </company>
</companies>
Parser Snippet
KXmlParser parser = new KXmlParser();
parser.setInput(new InputStreamReader(new ByteArrayInputStream(input.getBytes())));
parser.nextTag();
parser.require(XmlPullParser.START_TAG, null, "companies");
while(parser.nextTag() == XmlPullParser.START_TAG)
{
Company temp_company = new Company();
parser.require(XmlPullParser.START_TAG, null, "company");
String CompanyID = parser.getAttributeValue(0);
temp_company.putValue("CompanyId", CompanyID);
while(parser.nextTag() == XmlPullParser.START_TAG)
{
if(parser.getName() == "CompanyName")
{
temp_company.putValue("CompanyName", parser.nextText());
}
}
parser.require(XmlPullParser.END_TAG, null, "company");
listCompany.put(CompanyID, temp_company);
}
parser.require(XmlPullParser.END_TAG, null, "elements");
I guess I can see what is going wrong here. After you have matched the <company> tag and obtained the value of the CompanyId attribute, you enter a while loop. But observe what will happen at this point:
The first time you execute the while condition, the parser will match the <CompanyName> start tag, thus the if condition will be true and you will obtain the text inside the tag.
I am not too intimate with the inner workings of kXml but on the second iteration your parser state must be either pointing at the text node (that is inside the <CompanyName> tag) or at the end tag (ie. </CompanyName>). Either way, you while condition will fail because you are not at a start tag.
At this point you require that the next tag be the end tag of <company>, however, your state has still not changed and this will not be satisfied.
My best guess is that the internal pointer is pointing at the text node inside <CompanyName> and that is why you get the "unexpected type (position: Text: Test Company1..." message.
Related
I work with Umbraco version 8.9.1. I have a simple macro video to add local video (in Umbraco Media) in place of public url video. I also use a Search (IPublishedContentQuery) that return me a IEnumerable of PublishedSearchResult. It works well except when I use my macro video in a field, then the field (here body) throw an error : System.ArgumentNullException.
Apparently it's the mapping that cannot be done. The property is in the item.Content.Property and the item.Content.HasValue(property) return true.
public List<IPublishedProperty> CheckTheValues(PublishedSearchResult item, string searchValue)
{
foreach (var property in item.Content.Properties) // return me "body"
{
if (!item.Content.HasValue(property.Alias)) // HasValue return true
continue;
var contentValue = item.Content.Value(property.Alias); // throw System.ArgumentNullException
...
}
}
I suppose that's because the mapping cannot translate the macro in something known but it's awkward because I have the html code in my cache like <?UMBRACO_MACRO ... />.
Is there a way to add an alternative content to the macro (not on the video tag), I think about alt property that exists on html img to write an alternative text if the image doesn't exists ?
If not, is there a way to force to get the html code ? (to get the tag umbraco_macro in place of an error)
If not, is there a way to ignore the "not understand" part tags of the content "body" ? so return all except this macro tag.
If not, except with a try catch continue, is there a proper way to ignore this result from my search ?
Thanks a lot !
I need information on how to use the PXSubordinateSelector attribute with the Where type that you can allegedly set on the attribute. Does anybody know how to use this attribute?
Specifically, I need to filter the selector by a custom field in the EPCompanyTree table if possible. Not sure what tables this selector attribute usese. It seems to be tucked into the Acumatica black box. Something like this:
[PXSubordinateSelector(typeof(Where<EPCompanyTree.customField, Equal<{somevalue}>>))]
I've tried setting the Where to an arbitrary filter on the EPCompanyTree.sortorder field but, I'm getting an "is not bound" error when clicking on the lookup.
TIA!
The reason for this error is the defined Search in the GetCommand method of the PXSubordinateSelectorAttribute. Below is the disassembled code of that method:
private static Type GetCommand(Type where)
{
Type whereType = typeof(Where<CREmployee.userID, Equal<Current<AccessInfo.userID>>, Or<EPCompanyTreeMember.workGroupID, Owned<Current<AccessInfo.userID>>>>);
if (where != null)
{
whereType = BqlCommand.Compose(new Type[]
{
typeof(Where2<, >),
typeof(Where<CREmployee.userID, Equal<Current<AccessInfo.userID>>, Or<EPCompanyTreeMember.workGroupID, Owned<Current<AccessInfo.userID>>>>),
typeof(And<>),
where
});
}
return BqlCommand.Compose(new Type[]
{
typeof(Search5<, , , >),
typeof(CREmployee.bAccountID),
typeof(LeftJoin<EPCompanyTreeMember, On<EPCompanyTreeMember.userID, Equal<CREmployee.userID>>>),
whereType,
typeof(Aggregate<GroupBy<CREmployee.acctCD>>)
});
}
As you can see from code the Search is being organized on CREmployee with left joined EPCompanyTreeMember, meanwhile, your code is trying to add a condition on EPCompanyTree field which is not participating in the Search.
I just upgrade MvcSiteMapProvider from v3 to v4.6.3.
I see the upgrade note indicate:
In general, any reference to System.Web.SiteMap.Provider will need to be updated to MvcSiteMapProvider.SiteMaps.Current
I am trying to get the sitemap node by using:
SiteMaps.Current.FindSiteMapNode(rawUrl)
But it always return null
I looked into the code. In the sitemap it's actually calling the function:
protected virtual ISiteMapNode FindSiteMapNodeFromUrlMatch(IUrlKey urlToMatch)
{
if (this.urlTable.ContainsKey(urlToMatch))
{
return this.urlTable[urlToMatch];
}
return null;
}
It's trying to find a match in the urlTable.
I am using Default implementation of XmlSiteMapProvider .
It define var url = node.GetAttributeValue("url");
siteMapNode.Url = url;
siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");
So if I did not define url or urlResolver attribute in the .sitemap file. These variables a set to empty string, when generate the node.
And when this nodes are passed to AddNode function in SiteMap.
When adding the node
bool isMvcUrl = string.IsNullOrEmpty(node.UnresolvedUrl) && this.UsesDefaultUrlResolver(node);
this code will check if there is url or urlResolver
// Only store URLs if they are clickable and are configured using the Url
// property or provided by a custom URL resolver.
if (!isMvcUrl && node.Clickable)
{
url = this.siteMapChildStateFactory.CreateUrlKey(node);
// Check for duplicates (including matching or empty host names).
if (this.urlTable
.Where(k => string.Equals(k.Key.RootRelativeUrl, url.RootRelativeUrl, StringComparison.OrdinalIgnoreCase))
.Where(k => string.IsNullOrEmpty(k.Key.HostName) || string.IsNullOrEmpty(url.HostName) || string.Equals(k.Key.HostName, url.HostName, StringComparison.OrdinalIgnoreCase))
.Count() > 0)
{
var absoluteUrl = this.urlPath.ResolveUrl(node.UnresolvedUrl, string.IsNullOrEmpty(node.Protocol) ? Uri.UriSchemeHttp : node.Protocol, node.HostName);
throw new InvalidOperationException(string.Format(Resources.Messages.MultipleNodesWithIdenticalUrl, absoluteUrl));
}
}
// Add the URL
if (url != null)
{
this.urlTable[url] = node;
}
Finally no url is add to the urlTable, which result in FindSiteMapNode cannot find anything.
I am not sure if there needs to be specific configuration. Or should I implement custom XmlSiteMapProvider just add the url.
ISiteMapNodeProvider instances cannot use the FindSiteMapNode function for 2 reasons. The first you have already discovered is that finding by URL can only be done if you set the url attribute explicitly in the node configuration. The second reason is that the SiteMapBuilder doesn't add any of the nodes to the SiteMap until all of the ISiteMapNodeProvider instances have completed running, so it would be moot to add the URL to the URL table anyway.
It might help if you explain what you are trying to accomplish.
The ISiteMapNodeProvider classes have complete control over the data that is added to the SiteMapNode instances and they also have access to their parent SiteMapNode instance. This is generally all that is needed in order to populate the data. Looking up another SiteMapNode from the SiteMap object while populating the data is not supported. But as long as the node you are interested in is populated in the same ISiteMapNodeProvider instance, you can just get a reference to it later by storing it in a variable.
Update
Okay, I reread your question and your comment and it now just seems like you are looking in the wrong place. MvcSiteMapProvider v4 is no longer based on Microsoft's SiteMap provider model, so using XmlSiteMapProvider doesn't make sense, as it would sidestep the entire implementation. The only case where this might make sense is if you have a hybrid ASP.NET and ASP.NET MVC application that you want to keep a consitant menu structure between. See Upgrading from v3 to v4.
There are 2 stages to working with the data. The first stage (the ISiteMapBuilder and ISiteMapNodeProvider) loads the data from various sources (XML, .NET attributes, DynamicNodeProviders, and custom implementations of ISiteMapNodeProvider) and adds it to an object graph that starts at the SiteMap object. Much like Microsoft's model, this data is stored in a shared cache and only loaded when the cache expires. This is the stage you have been focusing on and it definitely doesn't make sense to lookup nodes here.
The second stage is when an individual request is made to access the data. This is where looking up data based on a URL might make sense, but there is already a built-in CurrentNode property that finds the node matching the current URL (or more likely the current route since we are dealing with MVC) which in most cases is the best approach to finding a node. Each node has a ParentNode and ChildNodes properties that can be used to walk up or down the tree from there.
In this second stage, you can access the SiteMap data at any point after the Application_Start event such as within a controller action, in one of the built in HTML helpers, an HTML helper template in the /Views/Shared/DisplayTemplates/ directory, or a custom HTML helper. This is the point in the application life cycle which you might call the lines SiteMaps.Current.FindSiteMapNode(rawUrl) or (more likely) SiteMaps.Current.CurrentNode to get an instance of the node so you can inspect its Attributes property (the custom attributes).
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
var currentNode = MvcSiteMapProvider.SiteMaps.Current.CurrentNode;
string permission = currentNode.Attributes.ContainsKey("permission") ? currentNode.Attributes["permission"].ToString() : string.Empty;
string programs = currentNode.Attributes.ContainsKey("programs") ? currentNode.Attributes["programs"].ToString() : string.Empty;
string agencies = currentNode.Attributes.ContainsKey("agencies") ? currentNode.Attributes["agencies"].ToString() : string.Empty;
// Do something with the custom attributes of the About page here
return View();
}
The most common usage of custom attributes is to use them from within a custom HTML helper template. Here is a custom version of the /Views/Shared/DisplayTemplates/SiteMapNodeModel.cshtml template that displays the custom attributes. Note that this template is called recursively by the Menu, SiteMapPath, and SiteMap HTML helpers. Have a look at this answer for more help if HTML helper customization is what you intend to do.
#model MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModel
#using System.Web.Mvc.Html
#using MvcSiteMapProvider.Web.Html.Models
#if (Model.IsCurrentNode && Model.SourceMetadata["HtmlHelper"].ToString() != "MvcSiteMapProvider.Web.Html.MenuHelper") {
<text>#Model.Title</text>
} else if (Model.IsClickable) {
if (string.IsNullOrEmpty(Model.Description))
{
#Model.Title
}
else
{
#Model.Title
}
} else {
<text>#Model.Title</text>
}
#string permission = Model.Attributes.ContainsKey("permission") ? Model.Attributes["permission"].ToString() : string.Empty
#string programs = Model.Attributes.ContainsKey("programs") ? Model.Attributes["programs"].ToString() : string.Empty
#string agencies = Model.Attributes.ContainsKey("agencies") ? Model.Attributes["agencies"].ToString() : string.Empty
<div>#permission</div>
<div>#programs</div>
<div>#agencies</div>
I am trying to get the parent document of a new response document so I can duplicate the functionality of form inheritance in xpages. The following is my code and the error being returned:
Error while executing JavaScript action expression
Script interpreter error, line=3, col=60: 'parentDoc' is null
JavaScript code
1: if (document2.isNewNote()) {
2: var parentDoc:NotesDocument = database.getDocumentByID(document2.getParentId());
3: getComponent("immediateParentSubject1").setValue(parentDoc.getItemValueString("Subject"));
4: }
I usually use a dataContext and getParentDocumentUNID() when I need a handle on the parent document for the variable "document". You can use this for a new document (not saved yet):
<xp:this.dataContexts>
<xp:dataContext var="parentDoc">
<xp:this.value><![CDATA[#{javascript:
try {
if (document.isResponse()) {
return database.getDocumentByUNID(document.getDocument().getParentDocumentUNID());
} else {
return "";
}
} catch(e) {
return "";
}}]]></xp:this.value>
</xp:dataContext>
</xp:this.dataContexts>
You can then use parentDoc in other controls and do parentDoc.getItemValueString("Subject") etc.
datasource.getParentId() does not return the NoteID as you might expect. It returns the UnID and that's why you need to use database.getDocumentByUNID as Per is doing.
Another way is to get the parent UnID from the URL:
param.get("parentId")
Consider also looking up the parent subject whenever a child is opened instead. That way it is stored only in one place which is always a good thing.
How do you deal with the fact, that URLs are case sensitive in xPages even for parameters? For example URL:
my_page.xsp?folderid=785478 ... is not the same as ...
my_page.xsp?FOLDERID=785478
How to make, for example, a proper check that params contain some key e.g.
param.containsKey("folderid") which desnt work when there is 'FOLDERID' in URL.
I'd suggest defining a couple convenience #Functions:
var #HasParam = function(parameter) {
var result:boolean = false;
for (var eachParam : param.keySet()) {
if (eachParam.toLowerCase() == parameter.toLowerCase()) {
result = true;
break;
}
}
return result;
};
var #GetParam = function(parameter) {
var result = "";
if (#HasParam(parameter)) {
for (var eachParam : param.keySet()) {
if (eachParam.toLowerCase() == parameter.toLowerCase()) {
result = param.get(eachParam);
break;
}
}
}
return result;
};
Then you can safely query the parameters without caring about case. For bonus points, you could add requestScope caching so that you can skip looping through the keySet if you're examining a parameter that you've previously looked at during the same request.
you may use this function:
context.getUrlParameter('param_name')
then test if it's null or not.
make sure to decide for one,so either upper or lowercase
other than that i'd suggest something like
KeyValuePair<string,string> kvp = null;
foreach(KeyValuePair<string,string> p in param)
{
if(UPPERCASE(p.Key) == UPPERCASE("folderid"))
{
kvp = p;
break;
}
}
syntax isn't correct and idk the uppercase method in c# right now,but you get the point
The easiest answer is ofcourse the obvious. Be sure that the parameters you are using througout your application are always the same on every url you are generating and know what to expect. A good approach to accomplish this is to create a ssjs function which generates url's for you according to the objects you submit.
In this function you could check which object you are receiving and with the use of keywords and so forth generate the correct url. This way generating twice a url with the same input parameters should always generate the exact same url.
another option would be just to double check with a bit of code like this
var key = "yourkey";
if(param.contains(#uppercase(key)) || param.contains(#lowercase(key)){
// do stuff
}
But should not be necesarry if the url you are parsing is generated by your own application
Edit after post of topic starter
Another option would be to grap the url directly from from the facescontext and to convert it to a string first. When it is a string you can parse the parameters yourself.
You can combine server side substitution/redirection to get around the issue that David mentioned. So a substitution rule will redirect incoming patern like this:
http://myhost/mypage/param (/mypage/* => which converts to - /dbpath/mypage.xsp?*) - substitution is tricky so please handle with care.
Also I believe I read somewhere that context.getUrlParameter is not case sensitive - can someone please confirm this.
Hope this helps.