Word VSTO CustomXMLNode.SelectSingleNode fails after Office upgrade - c#

A word vsto addin fails with exception on calling CustomXMLNode.SelectSingleNode.
The addin runs fine with word 2007 - 2013, but on version 2016 it fails with Reference to undeclared namespace prefix: 'ns0'.
I've made a workaround navigating the XML without the use of xpath and these methods, but still need to figure out how to solve this issue.
var xPathExpression = String.Format(
"{0}:{1}[1]",
customXml.NamespaceManager.LookupPrefix(xmlRef.DefaultNamespace),
xmlRef.ElementNames.DisplayText.LocalName);
groupMembers[j].SelectSingleNode(xPathExpression);
The resulting xPathExpression is
ns0:DisplayText[1]
The xml looks like this:
<MyXmlTest xmlns="http://www.myxmltest.com/document">
<Ribbon visible="true">
<Group name="xmlProperties">Document Properties</Group>
<Group name="xmlActions">Other Properties</Group>
</Ribbon>
<DocumentList>
<Document>
<Properties ribbonLabel="Hello World Menu">
<Property name="helloWorld">
<RibbonButton groupName="xmlActions">
<DisplayText>Hello World</DisplayText>
<PlaceholderText>N/A</PlaceholderText>
<Tooltip>Some text goes here.</Tooltip>
</RibbonButton>
<Content/>
</Property>
<Property name="title">
<RibbonButton groupName="xmlProperties">
<DisplayText>Hello World Text</DisplayText>
<PlaceholderText>N/A</PlaceholderText>
<Tooltip>Insert Hello World in Document</Tooltip>
</RibbonButton>
<Content>Testing</Content>
</Property>
</Properties>
</Document>
</DocumentList>
</MyXmlTest>

Usually, to execute XPath containing namespace prefix you need to pass along namespace manager containing the prefix-URI mapping. Since this option isn't available in your case, as a workaround, you can try to ignore namespaces by using local-name() :
*[local-name()='DisplayText'][1]

Related

Resharper External Attributes with MSTest's [DeploymentItem]

In certain cases (like when writing URIs in XAML), ReSharper magically figures out I am writing out a relative path to a file in the current project and offers very useful smart-completion for it, and a warning if I misspell something and get it wrong, and even goes to the file if I ctrl+click it.
Can I somehow tell ReSharper to do the same when I'm typing in the parameter to MSTest's DeploymentItem attribute?
This should work through an external annotation. Open the following file:
C:\Program Files (x86)\JetBrains\ReSharper\v7.1\Bin\ExternalAnnotations\Visual Studio\Microsoft.VisualStudio.QualityTools.UnitTestFramework.xml
(Or whatever version of Resharper you're using.)
Add these lines inside the assembly tag:
<member name="M:Microsoft.VisualStudio.TestTools.UnitTesting.DeploymentItemAttribute.#ctor(System.String)">
<parameter name="path">
<attribute ctor="M:JetBrains.Annotations.PathReferenceAttribute.#ctor" />
</parameter>
</member>
<member name="M:Microsoft.VisualStudio.TestTools.UnitTesting.DeploymentItemAttribute.#ctor(System.String,System.String)">
<parameter name="path">
<attribute ctor="M:JetBrains.Annotations.PathReferenceAttribute.#ctor" />
</parameter>
</member>
That tells Resharper to throw the PathReference attribute on the path parameter of both constructors of DeploymentItem.
However, after testing for some time now I cannot see this attribute working on anything that I try within the C# text editor. It could be that it doesn't work for my version (7.1), but I'm a bit stumped. Perhaps someone can add to this?

Irregular xml file processing

I need to process information from an XML-like file. Does anyone know some library/inbuild class (preferably c#) which might be useful to deal with that type of document (with not much effort) ?
Below is a piece of the XML :
<query>
<type id="excel" />
<ids>
<id value="47" />
<id value="2067" />
<id value="247" />
<id value="329" />
<id value="19" />
<id value="485" />
<id value="148" />
<id value="203" />
<id value="219" />
<id value="1503" />
<id value="7318" />
</ids>
<period value="Monthly" />
<start month="01" year="1990" />
<end month="12" year="2015" />
</query>
This appears to be a perfectly valid XML file.
There are System.Xml.XmlDocument class and System.Xml.Linq.XDocument class, both deal with parsing (and constructing) XML.
You can also build a class model and then use XmlSerializer class to deserialize the xml into a class hierarchical model instance.
Welcome to StackOverflow :D
There are 2 tools that should help you in dealing with it :
XSD.EXE will generate a schema and classes that you can add to your project
XSD2Code will generate classes from a schema as well as Serialize/Deserialize methods
Suggestion :
Use XSD.EXE to generate your schema then use XSD2Code to generate classes from that schema.
Both tools are free,
The first one you access it through the Developer Command Line :
xsd file.xml
The second one is a Visual Studio add-in : (tutorial on their site)
Do not forget to accept the answer if you are satisfied with it or ask for more details by editing your question.

How to use LINQ to get data from an XML file?

I have xml files which look like this:
<?xml version="1.0" encoding="utf-8"?>
<record id="177" restricted="false">
<type>record type</type>
<startdate>2000-10-10</startdate>
<enddate>2014-02-01</enddate>
<titles>
<title xml:lang="en" type="main">Main title</title>
<!-- only one title element with type main -->
<title xml:lang="de" type="official">German title</title>
<!-- can have more titles of type official -->
</titles>
<description>description of the record</description>
<categories>
<category id="122">
<name>category name</name>
<description>category description</description>
</category>
<!-- can have more categories -->
</categories>
<tags>
<tag id="5434">
<name>tag name</name>
<description>tag description</description>
</tag>
<!-- can have more tags -->
</tags>
</record>
How do I select the data from these xml files using LINQ, or should I use something else?
You can load xml into XDocument objects using either the Load() method
for files, or the Parse() method for strings:
var doc = XDocument.Load("your-file.xml");
// OR
var doc = XDocument.Parse(yourXmlString);
Then you can access the data using LINQ:
var titles =
from title in doc.XPathSelectElements("//title")
where title.Attribute("type").Value == "official"
select title.Value;
Was searching for examples of Xmlserializer and found this: How to Deserialize XML document
So why not to try. I did Ctrl+C and Edit -> Paste Special -> Paste XML As Classes in Visual Studio 2013 and... Whoa I got all the classes generated. One condition target framework must be 4.5 and this function is available from Visual Studio 2012+ (as stated in that post)

How Can i associate an aspect and his property to a document in C# DotCmis Alfresco

I am working in a .net web application than need to be able to create documents in Alfresco and then associate a particular aspect and his prperties to those documents.
I created my aspect (nameModel.xml, name-model-context.xml all this files in the extension folder, name.properties in messages folder and custom-slingshot-application-context.xml share-config-custom.xml in the web-extension folder) in /opt/bitnami/apache-tomcat/shared/classes/alfresco/ path.
In my C# code, i have two methods:
public void PutFile(CMISDocument document)
{
IObjectId cmisObjectFolder = (IObjectId)session.GetObject(document.FolderId);
IDictionary<string, object> properties = new Dictionary<string, object>();
properties[PropertyIds.Name] = document.ContentStreamFileName;
properties[PropertyIds.ObjectTypeId] = "cmis:document";
properties[PropertyIds.CreationDate] = DateTime.Now;
ContentStream contentStream = new ContentStream();
contentStream.FileName = document.ContentStreamFileName;
contentStream.MimeType = document.ContentStreamMimeType;
contentStream.Length = document.Stream.Length;
contentStream.Stream = document.Stream;
IObjectId objectId = session.CreateDocument(properties, cmisObjectFolder, contentStream, DotCMIS.Enums.VersioningState.None);
PutFileDetail(objectId,document.Owner);
}
internal void PutFileDetail(IObjectId objectId,string actorIdCard)
{
ICmisObject cmisObject = session.GetObject(objectId);
IDictionary<string, object> properties = new Dictionary<string, object>();
properties[PropertyIds.ObjectTypeId] = "adm:aridoctypBase";
properties["adm:actidcard"] = actorIdCard;
IObjectId newId = cmisObject.UpdateProperties(properties);
if (newId.Id == cmisObject.Id)
{
// the repository updated this object - refresh the object
cmisObject.Refresh();
}
else
{
// the repository created a new version - fetch the new version
cmisObject = session.GetObject(newId);
}
}
With this code i have as result a error:
The first one is for create the document and the second one is for add the aspect and his properties.
I was looking for a answer, and i finded this: http://docs.alfresco.com/4.0/index.jsp?topic=%2Fcom.alfresco.enterprise.doc%2Fconcepts%2Fopencmis-ext-intro.html
But a really do not know how install Alfresco OpenCMIS Extension; they say that i need put the jar file in my class path. But i do not know what is my class path in bitnami virtual machine.
Other thing is if i forgot something in the creation of my aspect.
pd: It is important but nor urgent for me, that the way to do it could be work if one day a need change Alfresco to Sharepoint or another else enterprise content management
I will apreciate any help.
Thanks! Do you know where can i see a good example? I think that the first point: i need change my model. In this moment i have the properties inside of aspect tags. I will need create the types and the properties ... can you tell me if i am going in good way...?
This is my model xml file (aridocsModel.xml) resume:
<?xml version="1.0" encoding="UTF-8"?>
<model name="adm:aridocsModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
...
<aspects>
<aspect name="adm:aridocsBase">
<title>AriDocs Base</title>
<properties>
<property name="adm:createdate">
<type>d:date</type>
</property>
<property name="adm:disabledate">
<type>d:date</type>
</property>
<property name="adm:artiddoc">
<type>d:text</type>
</property>
<property name="adm:accnumber">
<type>d:text</type>
</property>
<property name="adm:actidcard">
<type>d:text</type>
</property>
</properties>
</aspect>
</aspects>
</model>
Now, how i can not work with aspects; and i need types ...
<?xml version="1.0" encoding="UTF-8"?>
<model name="adm:aridocsModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
...
<types>
<type name="adm:aridoctypBase">
<title>Ari Docs Type Base</title>
<parent>cm:content</parent>
<properties>
<property name="adm:createdate">
<type>d:date</type>
</property>
<property name="adm:disabledate">
<type>d:date</type>
</property>
<property name="adm:artiddoc">
<type>d:text</type>
</property>
<property name="adm:accnumber">
<type>d:text</type>
</property>
<property name="adm:actidcard">
<type>d:text</type>
</property>
</properties>
</type>
</types>
...
<!-- i need put the aspect here... Even if i will work with types... -->
...
</model>
I will appreciate any advice.
You don't need the extensions on creating a document. The extension is only for managing aspects.
And from what I've heard the extension isn't available in all the languages, so I'm not sure if there is a .dll for you to include in your project.
Did you read these topics: integrate a .net application with alfresco using cmis
And: .net wcf and create document

SpringNet load configuration file from environment variable?

I use C# and Spring Net 1.3.2 in console app.
I got :
an app.cfg
a spring-context.xml
a environnement.xml file wich contains specific variables values according to the where the app is running : a folder for production, one for qa, and one for test.
What I want to achieve :
in my shell (windows), before launching the app with foo.bat, I do :
set environment="qa"
When Spring loads the context, it picks the value contained in the environment var (say qa), and loads the correct file : thus replacing : configuration/{environment}/vars.xml
by configuration/qa/vars.xml.
In my my spring-context.xml file, I got objects like this : value = ${connectionString.DB1}" where the value is defined inside each vars.xml file (remember, one for prod, one for qa...).
For now, I am not able to replace the ${environment} variable. So I did it programmatically by getting the value of ${environment} with System.Environment.GetEnvironmentVariable("environnement"); and using Path.Combine, load the two contexts myself :
reader.LoadObjectDefinitions(envPath);
reader.LoadObjectDefinitions("configuration/common/springContext.xml");
BUT :
I would like to make it by configuration.
I've been playing with (with no luck) :
<object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core">
<property name="VariableSources">
<list>
<object type="Spring.Objects.Factory.Config.EnvironmentVariableSource, Spring.Core"/>
</list>
</property>
</object>
<object name="appConfigPropertyHolder"
type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
<property name="EnvironmentVariableMode" value="Override"/>
</object>
Any ideas ?
Ok, after much research, it works!
<object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core">
<property name="VariableSources">
<list>
<object type="Spring.Objects.Factory.Config.EnvironmentVariableSource, Spring.Core"/>
<object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core">
<property name="Location" value="${root.config}/envars.properties" />
<property name="IgnoreMissingResources" value="false"/>
</object>
</list>
</property>
</object>
path to property file depends upon the environment variable.
Variables are replaced by the values obtained from the properties file.
I deploy one package + folder with 4 environment properties files
And I set my env var accordingly.
No need to mess with app.config or multiple Spring configuration files.

Categories

Resources