I am working with a CustomXMLPart that I identify by and attribute (#Id).
var xPath = "/ns0:customPartParent[1]/ChildNode[#Id='" + id + "']";
contentControl.XMLMapping.SetMapping(xpath, prefix, customPart)
When setting the xPath of the control to the above, looking at the mapping at runtime, the path stays with the Id - i.e.
/ns0:customPartParent[1]/ChildNode[#Id='eae2fd04-3a05-42c1-a154-0d7da47cca56']
But as soon as I provide a FULL path;
/ns0:customPartParent[1]/ChildNode[#Id='eae2fd04-3a05-42c1-a154-0d7da47cca56']/Value[1]/Item[1]/Fullname[1]
The #Id, gets replaced with the index of the part attached within the document.
/ns0:customPartParent[1]/ChildNode[2]/Value[1]/Item[1]/Fullname[1]
The reason this is an issue is because we have functionality that allows 2 documents to merge, where I copy the XMLPartNodes from one document and add it to the 2nd document's node(s) - if these are indexed, they will obviously look at the wrong items within the customXMLPart.
I would like to try force the #Id to stay so that when I move this part to another document, the part will be identified with the same #id and not by index?
Any ideas?
UPDATE: This only happens once you add Repeating content controls, as soon as I add my repating controls, all Id's disappear and reverts to index numbers.
Value of the content control before repeating item added:
/ns0:customPartParent[1]/ChildNode[#Id='1cae3c3f-c847-4a7c-91dc-5625a2228a11']/Value[1]/Item[1]/Fullname[1]
Value of the content control after repeating item added:
/ns0:customPartParent[1]/ChildNode[2]/Value[1]/Item[1]/Fullname[1]
Related
The Setup
Currently, CKEditor 5 does not support image captions for inline images. As our CMS needs to utilize both block and inline images, I wrote a plugin that extends schema and conversions with a custom <caption> element that works both for <imageInline> and <imageBlock> (and a custom, plaintext-only <alt> element for also have a nested editable for the image alternative text, but that's omitted here because it's not part of the issue).
It starts with a schema extension for <caption> to work for both image types:
schema.register('caption', {
allowIn: ['imageBlock', 'imageInline'],
allowContentOf: '$block',
isLimit: true
});
Then, several conversions and up-/downcast helpers from the original image packages #ckeditor/ckeditor5-image/... (image/imageblockediting.js, image/imageinlineediting.js, image/converters.js, image/utils.js, imagecaption/imagecaptionediting.js) are adapted and/or overwritten with higher priority custom versions to have an editable <caption> element both inside <imageBlock> and <imageInline>.
Both image types can have a linkHref attribute, which is implemented by extended, higher priority versions of upcastImageLink() and downcastImageLink() from #ckeditor/ckeditor5-link/src/linkimageediting.js.
Also, we need to backup and restore the <caption> element and all its child nodes when changing between block and inline images by listening to the imageStyleCommand, because the command itself obviously does not care for our custom <caption> structure (the caption should be visible all the time, so there is no need for a toggle as in the original caption package).
All in all, it's 400+ lines of code, so I won't post it here - you can get the idea by looking at the original code mentioned above.
Working Code
Now, for block images we have the same model/view structure and functionality as the original <imageBlock> version, and for <imageInline> the model looks like this (including the parent paragraph and some text; please ignore the <altContainer> structure):
Which gets converted to this view structure (again, ignore the <altcontainer> structure):
The Problem
When selecting an <inlineImage> and adding a link, the linkHref attribute is not only set on the <inlineImage> element itself (that's what we want), but also on all of the <caption>'s child nodes. So the model is looking like this:
And the view:
As you can see, the linked text from the original caption gets lost, too.
So how do you prevent this?
I'm assuming this is happening because <imageInline> is obviously registered as isInline:true, because when linking an <imageBlock> image this is not an issue! I've tried to fix this with a registerPostFixer() routine, but that can fix only parts of the problem.
I'm working around this problem now by cloning the whole <caption> structure before linking an image, and replacing the "buggy" version with the cloned one after the link command has finished.
There should be a more elegant way to tell the engine not to apply the linkHref attribute to the <caption> child nodes, and leaving existing linkHref attributes inside as is; which is also an issue when removing the link for the image: existing child linkHref attributes get also removed.
I would like to make a Word product catalog from data stored in an Access 2007 database. I can of course use the "mail merge" function in Word for the text data, but I dont know how to make the images show up! They are they stored as file paths in Access and jpg-files in a directory on the hard drive. The images should have a special size, be right aligned to the text paragraphs so that the text is wrapping on the left side (see attached image).
This is possible, but works better in older versions of Word. Unfortunately, you don't mention which version you're using...
Anyway, the key to the question is to use an IncludePicture field to bring the picture in; pass the file path to the field using the MergeField (nested fields). You can find more information on the internet, for example: http://homepage.swissonline.ch/cindymeister/mergfaq1.htm#DBPic
The problem with an IncludePicture field is that it can't be wrapped. But if your version of Word is not too old, tables CAN wrap, so you put the IncludePicture field into a table that's a single cell. Position the table, wrap it, etc.
My application under test has been developed by external suppliers so I have no control over the HTML structure. The application is extremely Javascript and Ajax heavy, with numerous dynamically generated buttons and auto-complete lists.
In other words, the characteristics of the pages are that they are filled with:
Elements with no fixed IDs (IDs are generated on the fly and have
numbers or other text dynamically added to them)
The same happens with some classes
Most of the times the buttons have no text associated with them since they are either custom coded 'down' arrows for lookup lists
(which aren't lookup lists but hidden divs) or '+' and '-' icons to
maximise or minimise portions of the content. -
It is therefore very difficult to identify these elements, especially the buttons.
I am trying to write a generic 'I click on the button near y' type of step so that it is not necessary to hardcode each and every button (assuming I can even get something to identify them with) into each and every test.
The thinking behind this is that normally there is a label of some sort close to the button at least.
What I want to to is to find the text label, then see if there is a button inside the same scope, and if there is not, move 'back' through the parent elements, and check if there is a button inside the scope of each parent level, up to 5 parents.
There might be all sorts of problems with this approach but I am just curious to see if this will work in general. I have run into some problems.
First I tried to use Xpaths, so I got the Xpath of the parent through :
$parentelement = $element->getParent();
$parentXpath->getXpath();
This would give me an Xpath of : (//html//span[text()='Cost center'])[1] and moving up through the parent elements all the time, they would become successively:
(//html//span[text()='Cost center'])[1]/..[1]
(//html//span[text()='Cost center'])[1]/..[1]/..[1]
and so forth.
The actual button is located in: (//html//span[text()='Cost center'])[1]/..[1]/..[1]//button but it has to go through all the parent elements in order to get there, so it will start with (//html//span[text()='Cost center'])[1]//button and should end with (//html//span[text()='Cost center'])[1]/..[1]/..[1]//button where it should find the button.
Trying to use Xpath I used:
$button_element = $session->getPage()->find('xpath',$parentXpath."//button")
I soon saw that the 'find' command appends an //html to the front of your xpath string so the Xpath that it tried to use ended up being (for each parent Xpath, but using this one as an example):
(//html(//html//span[text()='Cost center'])[1]/..[1])
I then stripped out the brackets as well as the //html, leaving me with:
//span[text()='Cost center'][1]/..[1]
but when I tried:
$button_element = $session->getPage()->find('xpath',$strippedParentXpath."//button")
I got the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '(//html//span[text()='Cost center'][1]/..[1]//button)[1]' is not a valid XPath expression
However, Firepath can execute this expression and does not show a syntax error for it, although it does not find the actual button (since the button is actually located one level up, where Firepath DOES find it).
So my question 1 is: What is wrong with my Xpath that I can't use it in the find? It actually looks as if //span[text()='Cost center'][1]//button does not throw the same exception, since as I said, I am looping through the parent Xpaths, and it starts with //span[text()='Cost center'][1]//button. It crashes on //span[text()='Cost center'][1]/..[1]//button.
My second option was to get the parent element each time, starting with finding the text on the page, but then to search for a button inside the scope of the parent element using the findbutton functionality.
Looping through the parent elements (up to a maximum of 5):
$parentelement = $parentelement->getParent();
$butonelement = $parentelement->findbutton('xxx');
In other words, find ANY button in the scope of the parent element. The problem I have is how to specify a generic 'button'.
One has to associate SOME text with the button (depicted by the 'xxx' above).
But this is a typical example of buttons in the application:
<button class="autocomplete_button" type="button" id="button_OM_1"> </button>
Where the class is used more than once, and the ID is auto-generated and not the same number all the time. There is no text associated with the button since the class specifies an image.
Question 2: So how can I use 'findbutton' to generically find a 'button' no specific distinguishing characteristics? Please note that I actually did try findbutton("button"), taking the chance that there might be a 'button' somewhere in a button, but this did not work either. At least, it doesn't work consistently and by that I mean that the same test randomly seems to either find or not find the same button when I run the test a couple of times.
After doing some more investigation on this issue I have found the following:
My method of trying to find the closest button to a piece of text via traversing 'up' through the scope of the divs and spans around the text (using xpath) is actually working.
What is NOT working is SAHI, which I am using as the web driver. In other words, it is not a Behat/Mink problem, it is SAHI specific issue.
I tried the same code using Selenium2 and it executes perfectly.
I still require an answer to question 2 - how can I use findbutton() without a specific parameter such as the ID, name or value but I will see if I can find an answer to that question separately and on the Behat user group since I do think that is a Behat/Mink specific issue.
I normaly use css selector and with that, I use to navigate to the class and ID's that the button is inside. it is easier than xpath I think, like you can use
$this->getSession ()->getPage ()->find ( 'css', '.parrent1 .parrent2 .autocomplete_button ' );
I think this will help you as you know which button your gonna use in each scenario
After joning data with my group I would like the elements in the enter selection to be added to a group (g-element) on top/highest up. Default is to append to the bottom.
The reason for this is that I want the object to visually appear below the all ready visible objects.
I know I can order and sort but I thought there might be an easier/better way to do this. I have done several manual things only to later find out "Oooh, they included a smart way to do that, EASILY."
D3 does have an insert method: https://github.com/mbostock/d3/wiki/Selections#wiki-insert
Excerpt from Reference
For instance, insert("div", ":first-child") will prepend child div
nodes to the current selection.
https://github.com/mbostock/d3/wiki/Selections#wiki-insert
I have tried different solutions to get the table node which I can identify as next sibling to the text node in the existing dom.
I used the following code, but the nextsibling is always null.
var element = browser.Element(Find.ByText(t => t.Contains("Individual Notices")));
if (element != null)
{
var table = element.NextSibling as Table;
}
Would appreciate the help if any one can guide me how to iterate through the rows which are there in the table next to the node "Individual Notices"
Thanks
You're having trouble as the Contains ends up not finding the element you want. Put Console.WriteLine("START" + element.Text+ "END"); in there right after the variable declaration/assignment, and I bet you'll see a whole lot of text output besides "Individual Notices".
If the Dom element you need ONLY has the text "Individual Notices" text, simply remove the lambda call and have Find.ByText("Individual Notices") and then table will have your table.
If this is not an option as the text isn't a known value, you might be able to search on a specific element type (eg: Div) so that parent nodes aren't being returned as the lambda contains result.
Edit:
Sometimes searching for an individual element by text is problematic due to browser oddities. At times text values shown to the user don't necessarily equal the text values seen by the DOM due to whitespaces being added or removed. Basically you might think you have "Individual Notices" but WatiN might see "Individual Notices " <- See the space at the end. The way I run not being able to find a particular element after easy/obvious methods are exhausted is to just iterate through the elements in WatiN code by searching for what I think should find it and then flashing the elements found and/or writing to the console. If not found, widen the search. Repeat as needed.