Xpath Part NULL, with xpaths set via content control toolkit - xpath

I've been able to set, via code, the xpaths for the placeholders found in the document.
for (Object o : finderSdtRun.results) {
if (o instanceof SdtRun){
SdtPr sdtPr=((SdtRun) o).getSdtPr();
Tag t = sdtPr.getTag();
CTDataBinding ctDataBinding = Context.getWmlObjectFactory().createCTDataBinding();
//JAXBElement jaxbDB = Context.getWmlObjectFactory().createSdtPrDataBinding(ctDataBinding);
sdtPr.setDataBinding(ctDataBinding);
ctDataBinding.setXpath("tuttappostaferragost");
ctDataBinding.setStoreItemID("something");
ObjectFactory factory = new org.opendope.xpaths.ObjectFactory();
DataBinding db = factory.createXpathsXpathDataBinding();
db.setXpath("tuttappostaferragost");
db.setStoreItemID("something");
Xpaths.Xpath xp = factory.createXpathsXpath();
xp.setDataBinding(db);
xp.setId("something");
try {
wordMLPackage.getMainDocumentPart().getXPathsPart().getContents().getXpath().add(xp);
} catch (Docx4JException e) {
e.printStackTrace();
}
;
The problem is that, once set, they are not recognized by word, so I thought to add the created Xpaths to a new XpathPart, and then add it to the main Document part.
But I failed because the method:
wordMLPackage.getMainDocumentPart().getXPathsPart()
returns null. This sounded reasonable, since only content control was set, without any Xpath.
Then I set the Xpaths via content control toolkit and the same line of code like above, returned me null, which added a lot of confusion in my yet confused ideas.
Is there any way to tell the document that new Xpath have been added to the document?
I mean, if there is a way to add Xpath via code (the w:databinding w:storedItemId tags), why it is not possible to make it work?
In general I want to add Xpath and all information necessary, via code, avoiding the use of any toolkit.
Thank you :D

First, you have to decide whether you want plain old Word databinding, or the additional OpenDoPE capabilities (which use the content control tag to support repeats, conditionals etc).
You only need an XPaths part if you are using the OpenDoPE extensions.
I'll assume for now that you are just looking to do basic Word content control databinding.
To set that up programmatically, you need to add a custom xml part, and a rel from it to its itemProps.xml part, which contains something like:
<ds:datastoreItem ds:itemID="{5448916C-134B-45E6-B8FE-88CC1FFC17C3}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml">
<ds:schemaRefs/>
</ds:datastoreItem>
(to add a part B to part A, use partA.addTargetPart)
You can see it is this part with gives the custom xml part its itemID; this corresponds with the value you set in:
DataBinding db = factory.createXpathsXpathDataBinding();
db.setStoreItemID("something");
Then, set the XPath via the method you were using.

Related

How to edit default code generation in VS22

I want to modify how some code in Visual Studio 22 is generated.
For instance, in methods I can generate null check on using the Add null check (MS docs link) for arguments in the following way.
public void MyMethod(object parameter)
{
if (object is null)
{
throw new ArgumentNullException(nameof(parameter));
}
// rest of the method
// ...
}
What I would like to be generated is this:
public void MyMethod(object parameter)
{
if (object is null) throw new ArgumentNullException(nameof(parameter));
// rest of the method
// ...
}
I was looking at code snippet settings and refactoring settings but I can not find the Add null check option anywhere. Let alone change it.
The best option I came up with is to create a code snippet (MS docs link) but that does not serve my purpose fully.
Is there an option I can modify to say how is the code generated?
Rewriting an answer by canton7 from the comments:
The Add null check is not generated by any code snippet. Rather it is based on the standard analyzer infrastructure (defined here and seen here). This means it is just a semantically generated if statement with a throw inside of it. Then based on your .editorconfig (or defaults if not specified) it formates the code accordingly.
One is left with the following options:
Edit the .editorconfig file to make the code format as pleased. Note that this approach applies globally.
Wait for the C# 11 !! syntax.
Write your own analyzer and code fix (tutorial).
Edit it by hand :).

meta fields using elasticsearch-dsl

I'm looking at the changelog for the elasticsearch-dsl python library, and one of the comments says:
you can no longer access meta fields on a Document instance by
specifying ._id or similar. Instead all access needs to happen via the
.meta attribute.
Can I get a little more color on that? My old (5.x) code did this
self._id = a_nice_natural_identiifer
How should that be replaced?
self.meta._id = a_nice_natural_identifier
or
self.meta['_id'] = a_nice_natural_identifier
or
self.meta['id'] = a_nice_natural_identifier
It appears that the correct answer is
self.meta['id'] = a_nice_natural_identifier
(Interestingly, you can also set meta properties at construction time by doing)
foo = SomeSubclassOfDocument(_id=a_nice_natural_identifier)

CodedUI assert a nonexistent element

my problem is that I want to check that an element is not displayed. In other words I want to check that an element was deleted.
So I am developing an automatic test that has a option to disable comments. I want to check that the textfield for the comments is nonexistent. Is there any easy way to do this?
You need to distinguish between the element (a text field or something) being not displayed and it being empty.
If the field is displayed but is empty then a simple assertion that the value is the empty string will work.
If the field is not displayed at all then an attempt on an assertion will fail with a control not found exception. The relevant code can be enclosed within a try-catch block that expects to catch the exception
try {
... access the control...;
Assert.Fail("The control was found but it should not be present.");
}
catch (UITestControlNotFoundException ) {
// Success path.
}
Make sure that the ... access the control...; checks for the correct level in thy control hierarchy. You may also want to enclose it with code to fail quickly when the control is not present, by default Coded UI may wait in case the application is slow to draw the control.
Try this :
Bool isExists = (Boolean)BrowserWindow.ExecuteScript("return $('#yourcontrolId').length > 0;");
if(isExists)
Assert.Fail("Control is not deleted");
// Success Code

how to extract data using jtidy and xpath

i have to extract d company name and face value from
http://money.rediff.com/companies/20-microns-ltd/15110088
i noticed that this task could be accomplished using xpath api.
since this is an html page, i am using jtidy parser.
this is the xpath for the face value which i have to extract.
/html/body/div[4]/div[6]/div[9]/div/table/tbody/tr[4]/td[2]
This is my code
URL oracle = new URL("http://money.rediff.com/companies/20-microns-ltd/15110088");
URLConnection yc = oracle.openConnection();
InputStream is = yc.getInputStream();
is = oracle.openStream();
Tidy tidy = new Tidy();
tidy.setQuiet(true);
tidy.setShowWarnings(false);
Document tidyDOM = tidy.parseDOM(is, null);
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
String expression = "/html";
XPathExpression xPathExpression = xPath.compile(expression);
Object result = xPathExpression.evaluate(tidyDOM,XPathConstants.NODESET);
System.out.println(result.toString());
please guide me further, because, i cannot find a right solution for the above
Try not to use "full" xpaths.
//div[#id='leftcontainer']//div[9]//table//tr[4]/td[2]
is better than
/html/body/.../.../.../.../.../...
Most HTML pages are not valid or even well-formed. So the DOM structure may change when processed by "real-world HTML parsers". For example, a <tbody> may be inserted under <table> if there isn't one. Things are worse when different HTML parsers generate different DOM trees so one XPath may be valid for one parser, but not the other. I would rather use "wildcards" like table//tr[4] instead of table/tbody/tr[4] or table/tr[4] so that I can forget about <tbody>. Such expressions are more robust when used against the messy real-world HTML pages.
You can use Firepath, a plugin for Firebug which is then a plugin for Firefox, to debug XPath expressions.
p.s. You can try my JHQL (http://github.com/wks/jhql) project for exactly this task. You will like it if you have more pages to extract data from.

Copy object values in Visual Studio debug mode

In Visual Studio debug mode it's possible to hover over variables to show their value and then right-click to "Copy", "Copy Expression" or "Copy Value".
In case the variable is an object and not just a basic type, there's a + sign to expand and explore the object. It there a way to copy all that into the clipboard?
In the immediate window, type
?name_of_variable
This will print out everything, and you can manually copy that anywhere you want, or use the immediate window's logging features to automatically write it to a file.
UPDATE: I assume you were asking how to copy/paste the nested structure of the values so that you could either search it textually, or so that you can save it on the side and then later compare the object's state to it. If I'm right, you might want to check out the commercial extension to Visual Studio that I created, called OzCode, which lets you do these thing much more easily through the "Search" and "Compare" features.
UPDATE 2 To answer #ppumkin's question, our new EAP has a new Export feature allows users to Export the variable values to Json, XML, Excel, or C# code.
Full disclosure: I'm the co-creator of the tool I described here.
You can run below code in immediate window and it will export to an xml file the serialized XML representation of an object:
(new System.Xml.Serialization.XmlSerializer(obj.GetType())).Serialize(new System.IO.StreamWriter(#"c:\temp\text.xml"), obj)
Source: Visual Studio how to serialize object from debugger
Most popular answer from https://stackoverflow.com/a/23362097/2680660:
With any luck you have Json.Net in you appdomain already. In which
case pop this into your Immediate window:
Newtonsoft.Json.JsonConvert.SerializeObject(someVariable)
Edit: With .NET Core 3.0, the following works too:
System.Text.Json.JsonSerializer.Serialize(someVariable)
There is a extension called Object Exporter that does this conveniently.
http://www.omarelabd.net/exporting-objects-from-the-visual-studio-debugger/
Extension: https://visualstudiogallery.msdn.microsoft.com/c6a21c68-f815-4895-999f-cd0885d8774f
You can add a watch for that object, and in the watch window, expand and select everything you want to copy and then copy it.
By using attributes to decorate your classes and methods you can have a specific value from your object display during debugging with the DebuggerDisplay attribute e.g.
[DebuggerDisplay("Person - {Name} is {Age} years old")]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
I always use:
string myJsonString = JsonConvert.SerializeObject(<some object>);
Then I copy the string value which unfortunately also copies the back slashes.
To remove the backlashes go here:
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_replace
Then within the <p id="demo">Visit Microsoft!</p> element replace the text with the text you copied.
then replace the var res = str.replace("Microsoft", "W3Schools"); line with
var res = str.replace(/\\/g, '')
Run these new changes but don't forget to click the "try it" button on the right.
Now you should have all the text of the object in json format that you can drop in a json formatter like http://jsonformatter.org or to create a POCO you can now use http://json2csharp.com/
ObjectDumper.NET
This is an awesome way!
You probably need this data for a unit test, so create a Sandbox.cs temporary test or you can create a Console App.
Make sure to get NuGet package, ObjectDumper.NET, not ObjectDumper.
Run this test (or console app)
View test output or text file to get the C# initializer code!
Code:
[TestClass]
public class Sandbox
{
[TestMethod]
public void GetInitializerCode()
{
var db = TestServices.GetDbContext();
var list = db.MyObjects.ToList();
var literal = ObjectDumper.Dump(list, new DumpOptions
{
DumpStyle = DumpStyle.CSharp,
IndentSize = 4
});
Console.WriteLine(literal); // Some test runners will truncate this, so use the file in that case.
File.WriteAllText(#"C:\temp\dump.txt", literal);
}
}
I used to use Object Exporter, but it is 5 years old and no longer supported in Visual Studio. It seems like Visual Studio Extensions come and go, but let's hope this NuGet package is here to stay! (Also it is actively maintained as of this writing.)
Google led me to this 8-year-old question and I ended up using ObjectDumper to achieve something very similar to copy-pasting debugger data. It was a breeze.
I know the question asked specifically about information from the debugger, but ObjectDumper gives information that is basically the same. I'm assuming those who google this question are like me and just need the data for debugging purposes and don't care whether it technically comes from the debugger or not.
I know I'm a bit late to the party, but I wrote a JSON implementation for serializing an object, if you prefer to have JSON output. Uses Newtonsoft.Json reference.
private static void WriteDebugJSON (dynamic obj, string filePath)
{
using (StreamWriter d = new StreamWriter(filePath))
{
d.Write(JsonConvert.SerializeObject(obj));
}
}
I've just right clicked on the variable and selected AddWatch, that's bring up watch window that consists of all the values. I selected all and paste it in a text a text editor, that's all.
Object Dumper is a free and open source extension for Visual Studio and Visual Studio Code.
"Dump as" commands are available via context menu in the Code and Immediate windows.
It's exporting objects to:
C# object initialization code,
JSON,
Visual Basic object initialization code,
XML,
YAML.
I believe that combined with the Diff tool it can be helpful.
I'm the author of this tool.
if you have a list and you want to find a specific variable:
In the immediate window, type
myList.Any(s => s.ID == 5062);
if this returns true
var myDebugVar = myList.FirstOrDefault(s => s.ID == 5062);
?myDebugVar
useful tips here, I'll add my preference for when i next end up here asking this question again in the future.
if you don't mind adding an extension that doesn't require output files or such there's the Hex Visualizer extension for visual studio, by mladen mihajlovic, he's done versions since 2015.
provides a nice display of the array via the usual magnifine glass view object from the local variables window.
https://marketplace.visualstudio.com/items?itemName=Mika76.HexVisualizer2019 is the 2019 version.
If you're in debug mode, you can copy any variable by writing copy() in the debug terminal.
This works with nested objects and also removes truncation and copies the complete value.
Tip: you can right click a variable, and click Copy as Expression and then paste that in the copy-function.
System.IO.File.WriteAllText("b.json", page.DebugInfo().ToJson())
Works great to avoid to deal with string debug format " for quote.
As #OmerRaviv says, you can go to Debug → Windows → Immediate where you can type:
myVariable
(as #bombek pointed out in the comments you don't need the question mark) although as some have found this limits to 100 lines.
I found a better way was to right click the variable → Add Watch, then press the + for anything I wanted to expand, then used #GeneWhitaker's solution, which is Ctrl+A, then copy Ctrl+C and paste into a text editor Ctrl+V.

Resources