I'm working with csproj files, and I'm trying to write a cmdlet that extracts all of the files referenced by a project file. This will include all of the Compile, EmbeddedResource, Resource, Content, and None elements (more importantly, their #Include values) but I specifically want to exclude the Reference elements as they refer to dlls, which aren't of concern to me.
I don't have a ton of experience, but I would think the xpath expression I would want would look something like this
$projectFile | Select-Xml -namespace #{msb="http://schemas.microsoft.com/developer/msbuild/2003"} -xpath "//msb:ItemGroup/*[not(self::node() = msb:Reference) and #Include]"
However, as soon as I try to introduce the self::node() my expression returns no nodes. I'm not 100% sure that self::node() is the right way to be doing this though. Any idea what I would change to make it return, conceptually, "all Include attribute values for nodes that are not Reference elements that are child elements of an ItemGroup element?"
I think that you need:
//msb:ItemGroup/*[not(self::msb:Reference)]/#Include
Meaning: all the Include attributes of any child of msb:ItemGroup except for msb:Reference, in the whole document
Related
I am recently brushing up my skills in TOSCA, I was working on it 2 years ago and switched to Selenium, I noticed that the new TOSCA allows identification using Xpath, and I am really familiar with it now, however, I cannot make it work in TOSCA and I am sure the object identification works because I am testing my xpath in google chrome developer tools.
Something as simple as (//*[text()='Forgot Password?'])[1] does not seem to be working. Could I be missing something?
This is the webpage I am using as reference for this example:
https://www.freecrm.com/index.html
XPath certainly can be used to identify elements of an HTML web UI in Tosca.
Since the question was originally posted, the "Forgot Password?" link at https://www.freecrm.com/index.html appears to have changed so that it's text is now "Forgot your password?" and is actually located at https://ui.freecrm.com/.
To account for that change, this answer uses "(//*[text()='Forgot your password?'])[1]" instead of the expression provided in the original post.
With the text modification, the expression works to idenfity the element in XScan after wrapping it in double quotes:
"(//*[text()='Forgot your password?'])[1]"
Some things to keep in mind when using XPath in Tosca:
It seems that XPath expressions need to be wrapped in double quotes (") so that XScan knows when to start evaluating XPath instead of using its normal rules. Looking closely at the expression that is pregenerated when XScan starts, we see that it is wrapped in double quotes:
"id('ui')/div[1]/div[1]/div[1]/a[1]"
A valid XPath expression doesn't necessarily guarantee uniqueness, so it is helpful to pay attention to any feedback messages at the bottom of XScan. There is a significant difference between "The selected element was not found" and "The selected element is not unique". The former simply indicates XScan can't find a match, the latter indicates that XScan matches successfully, but cannot uniquely identify the element.
My experience has been that it helps to explicitly identify the element to reduce the possibility of ambiguity. If the idea is to target the anchor element in order for tests to click a link, then reducing scope from any element i.e. "(//*[text()='Forgot your Password?'])[1]" to only match anchor elements with that text "//a[text()='Forgot your password?']".
In general, Tricentis (or at least the trainers with whom I have spoken) recommends using methods other than XPath to identify a target if they are available. That said, in my experience I've had better luck with XPath than with "Identify by Anchor".
An XPath expression is visible and editable in the XModuleAttribute properties without having to rescan. Personally, I find it easier to work with than the XML value of the RelativeId property that is generated when using Identify by Anchor.
With Anchor, I've had issues where XModuleAttributes scanned in one browser can no longer be found when switching to another browser, specifically from IE to Chrome. With XPath, I've not had these issues.
While XPath works well to identify the properties of one element with attributes of another because it can identify the relationship between them (very common with controls in Angular applications), the same can often be accomplished by adapting the engine layer using the TBox API (i.e. building a custom control). This requires some initial work up front from developer resources, but it can significantly improve how tests steer these controls in addition to reducing the need for Automation Specialists to have to rely on XPath.
What I know is that you can identify elements with XPath when working with XML messages in Tosca API testing. Your use case seems to be UI testing, but I am not sure about that.
Did you try to use XScan to scan the page? Usually Tosca automatically calculates an XPath expression for you that you can use immediately.
Please see the manual for details.
If it still does not work please try to be more specific? What isn't working? Error message? Unexpected behavior? ...
Tosca provides its set of attributes for locating any type of elements. You can directly select any number of attributes you want to make your element unique along with index of that element. Just make sure that you are not using any dynamic values in 'id' or 'class-name' of that element, also the index range is not so large like 20 out of 100; it could be 5 out of 10, which will be helpful if you need to update it in future.
Also take help of parent elements which will be uniquely located easily and then locate your expected element.
TOSCA provide various ways to locate an element just like selenium plus in addition it will provide other properties also.Under transition properties you will find x path and it will be absolute x path since you know selenium you know the difference between absolute and relative x path. I would suggest you to go with.
1.Identify by ID OR name
2. Identify by anchor
if your relative x path is not working
Try load all properties on the right side bottom. But it showed for me without clicking on it. See here
I'm embarking on a new project with eXist. We'll be storing a few hundred TEI XML documents that represent manuscripts. A number of things we want to capture are repetitve, mainly people and places. My colleague has asked the TEI community about strategies for representing what we want to capture and using XInclude had been suggested as a way of reducing duplication.
I've had a quick play with adding an XInclude into a document and the serialized XML does render the include XML file. However, the included text was missing from an XQuery. I notice in the eXist docs (http://exist-db.org/exist/apps/doc/xinclude.xml) that:
eXist-db expands XIncludes at serialization time, which means that the
query engine will see the XInclude tags before they are expanded. You
therefore cannot query across XIncludes - unless you create your own
code (e.g. an XQuery function) for it. We would certainly like to
support queries over xincluded content in the future though.
What is the best practice for querying files that use XInclude?
I'm wondering whether I should have a 'job' that serializes the source TEI XML files to expand the XIncludes and store these files in a separate collection? In that case, would file:serialize be the correct function for this task?
We are at the start of the project, so any advice appreciated.
Can you describe what kind of query you tried that was missing the text?
Generally, since the files referenced via XInclude are well-formed xml documents, you can use collections (folders) to organise your queries in exist-db. So instead of for $search in doc("mydoc.xml") you could for $search in collection('/app/mydata')/*
more elaborate answers would follow the attribute of the unexpanded xinclude statement in source document and find the matching element in the target, but its difficult to abstract that without a concrete MWE.
have you tried to create a temporary and expanded fragment in a let clause, and query that instead of the stored xml?
Beware of namespaces !
Hope this helps, and greetings to Sebastiaan.
I am looking for a way to separate the repetitive html codes from web pages, and for this I am planning to use the macro functionality. The problem here is for every macro I need to put this macro in a file, or put some of them in a file and include this in the template file.
What I need is to include once just the directory name something like
<#import "/tags/widgetDirectory" as widgets />
here the /tags/widgetDirectory is a directory , and every files here can be seen as a macro defined.
when I need to insert a code part from a file from this directory lets say slide.ftl I will just use
<#widgets.slider />
the system will check for slider.ftl in the /tags/widgetDirectory directory . here the slider.ftl can have <#macro> as first and as last line , or these can transparently added and system can load it as a macro
this will easy my designer work.
Maybe there is better way for doing this kind of widgets/components based web design ?
best regards,
This feature (importing directories) is something that's planned for FM actually... but it won't happen anytime soon. But I guess it can be solved fairly well with a hack right now. Instead of #import, use your own TemplateMethodModelEx, that you could use like <#assign widgets = importDirectory('/tags/widgetDirectory') >. This will return a TemplateHashModel that's also implemented by you and is bound to the directory path. When an item of that hash is get, it uses Environment.getCurrentEnvironment().include. The included file is expected to create a macro with name __main or something. So then you get that variable with Environment.getCurrentNamespace().get("__main") and return it as the result of the hash lookup. Of course this hash should also maintain a cache, so that if the same item is get twice, it wont include the template for the second time, just return the macro extracted earlier. This can be developer further, so that if the include file didn't define __main, then it's supposed that it prints directly to the output, and so it will be included again, when the "tag" is called again.
I have a structure like this:
<sv:a>
<sv:b sv:name="one"/>
<sv:b sv:name="two"/>
<sv:c sv:name="exclude"/>
<sv:b sv:name="error"/>
<sv:a>
I am trying to get all a's and b's but exclude from my search the content of any c.
I have this structure so far for my xpath query
//*[not(name()='error') and jcr:contains(*, 'searchInput')]
I want to add something to this to essentially say, "do not give me any node named exclude" or maybe a better way to put it is "exclude any node named exclude from the search". I am not sure if I can do that using the path initially used of //* and just filtering a different way. I know I cannot just say not(name()='exclude') because it is only looking at one level below root and only excludes nodes at that level.
Is there a way to search 1 more level below and exclude certain nodes by their name or search everything in the entire document and exclude those nodes of a particular name?
Im not sure it matters, but I am working the CMS Magnolia and trying to make a site search. I hit a limitation using jcr sql2 and cannot do what I am trying to do here as far as I have found in researching this.
EDIT:
Based on answers and comments, here is what I am looking at now:
//*[not(#sv:name='exclude' or #sv:name='error') and jcr:contains(*, 'searchInput)]
I still seem to be getting the 'exclude' results so I must either not be registering 'sv:' correctly or missing something in the query needed to exclude some of the results from the search.
I want to add something to this to essentially say, "do not give me any node named exclude"
That's easy: Nodes (elements) named exclude can be selected via the self axis,
using *[self::exclude]. Corollary: An element not named exclude is *[not(self::exclude)].
But I think you don't refer to element names. You don't have any <exclude> elements in your input.
You actually seem to refer to attributes.
//*[not(#sv:name = 'error' or #sv:name = 'exclude') and jcr:contains(*, 'searchInput')]
I am trying to get all a's and b's but exclude from my search the content of any c.
You can't, at least not with pure XPath. XPath is a language for selecting nodes out of an XML tree, not for building new trees that are different. An XPath expression can either select the a or not select the a, but it can't give you a new a element that has only some of the children of the original a and not others.
I need to programatically extract information from a solution which contains almost 150 projects in it. The solution file is not flat though, so some of the projects are organized into folders, the folder hierarchy can be more levels deep.
This fits a recursive solution: I could write a function, which enumerates a list, and if the element is a project it would examine it, if it is a folder it would go into the folder and recursively call itself to examine the folder's content. The gist of it:
$dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("visualstudio.dte.11.0")
function traverseproject {
param([object]$prjnode, [int]$level)
if ($prjnode.Kind -eq "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}")
{
Write $prjnode.Name
Write $level
}
if ($prjnode.Kind -eq "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}")
{
foreach ($prjsubnode in $prjnode)
{
traverseproject($prjsubnode, $level + 1)
}
}
}
foreach($prjn in $dte.solution.projects)
{
traverseproject($prjn, 0)
}
The problem is that the $prjnode object what the recursive function gets is weird.
Write $prjnode.Name doesn't output anything. Probably for the same reason I cannot iterate through the nodes of the folder object. Right now in the code above it's foreach ($prjsubnode in $prjnode), that just doesn't do anything silently. I tried foreach ($prjsubnode in $prjnode.ProjectItems), that gives error. I tried any kind of combinations.
From the error messages it seems that the $prjnode is type of a DTE ProjectItem link, 8E2F1269-185E-43C7-8899-950AD2769CCF. I can print out the Count property and it seems valid, but I don't see any property on the interface where I could get a hold of the contained elements. So maybe that's why I cannot iterate through? There's no way? I see the Visual Basic example at the bottom of the MSDN page I linked, but I need a working PowerShell solution.
The first call of the function seems to work OK, for example it sees the $prjnode.Kind property, but after the first recursive call things are lost.
Since you're already loading the dte, Check out http://studioshell.codeplex.com/
The feature that helps you the most:
Manage your projects, references, breakpoints, stack frame locals, menus, toolbars, Visual Studio settings, IDE windows, and even your code from PowerShell scripts, all in a consistent and discoverable way.
Here is how you can get all loaded projects with StudioShell
$projects = ls -path "DTE:\solution\Projects" -recurse
| where {$_.FileName -match ".csproj"}
Note that it may take up to 15 minutes for big solutions.