Check if an XSLT expects parameters? - c#

Is there anyway to check with C# code , to see if an XSLT expects parameters?

XSLT is XML, so you can load the file into a XDocument and query it to see if there are any parameter elements defined on the top element.

Evaluate this XPath expression against the XML document that contains the XSLT file:
/*/xsl:param
If the result contains at least one node, then the xslt stylesheet contains at least one global xsl:param -- and the main purpose of a global xsl:param is to be set externally by the invoker of the transformation.
where you have to add the XSLT namespace and associate it with the "xsl:" prefix using an XmlNamespaceManager object.

Related

Getting Xml from an embedded code in Xslt

I want to transform my Xml with a Xslt file. Can I access to the Xml that is transforming with Xslt in an embedded code piece using C#.
<![CDATA[
public string GetSomething(string path)
{
// Get the whole Xml that is transforming
// And do something with it
// return result
}
]]>
<xsl:value-of select ="GetSomething(courier:_appointment)"/>
Is it possible?
Thanks in advance,
There is some scripting support inside xslt, via <msxsl:script>, however: it is probably a better idea to use an extension object. Basically, you write a regular C# object (although you need to mark it as COM-callable, IIRC), and add it via XsltArgumentList, in particular AddExtensionObject - and in the process associate it with a particular urn. Your xslt then declares an xml namespace-alias for the url (i.e. xmlns:myExtension="blah blah"), and uses myExtension:someMethod(...) in the code.
There is a full example on MSDN.

Difference between namespace in XML

I'm creating XML document using XDocument in C#.
I have a question.
Is
<Simple xmlns = "Example"></Simple>
equivalent to
<Example:Simple></Example:Simple>
?
I tried to get second solution with XNamespace and XElement in C#, but I get only first.
No.
The first example creates a Simple element in the Example namespace (note that namespaces are usually expressed as URIs)
The second example creates a Simple element in whatever namespace is associated with the Example prefix (as defined by an xmlns attribute).
These would be equivalent:
<xml xmlns="http://example.com/myNameSpace">
<Simple></Simple>
</xml>
<xml xmlns="http://example.com/myNameSpace" xmlns:Example="http://example.com/myNameSpace">
<Example:Simple></Example:Simple>
</xml>
In the first example, you have defined a default namespace which applies to any element/attribute that is not prefixed with its own namespace.
In the second example, you have not defined a namespace.
No, because xml namespaces allow for characters which aren't supported by element names, you can't prefix an element tag name with its namespace like that.
Add a namespace prefix, like so:
<alias:Simple xmlns:alias = "Example"></alias:Simple>
No, but it's equivalent to:
<Example:Simple xmlns:Example="Example"></Example:Simple>
It's a bad idea to use relative URIs as the namespace name, since this XML now has a different namespace depending on where it came from. So always give the full URI. E.g if the XML was being received from http://example.net/somePlace/someXML then the relative URI Example expands to http://example.net/somePlace/Example, so use it fully:
<Example:Simple xmlns:Example="http://example.net/somePlace/Example"></Example:Simple>
OR
<Simple xmlns="http://example.net/somePlace/Example"></Simple>
Otherwise if someone saved it in C:\Documents then on opening it again it becomes the equivalent to:
<Simple xmlns="file:///C|/Documents/Example"></Simple>
Which means that the meaning of Simple here is completely different to that when it was first downloaded.

Parsing a file containing xml elements in C#

I have a big xml file which is composed of multiple xml files. The file structure is like this.
<xml1>
</xml1>
<xml2>
</xml2>
<xml3>
</xml3>
.
.
<xmln>
</xmln>
I want to process each XML file by a LINQ statement but I am not sure how to extract each XML element individually from the file and continue the iteration until the end. I figured experts here would be able to give me the nudge I am looking for. My requirement is to extract the individual elements so i could load into a XDoc element for further processing and continue on through the subsequent elements. Any help on this would be greatly appreciated.
Thanks for reading!!
Assuming each element is a valid XML, you can wrap your document in a top-level tag and then load it just fine:
<wrap>
<xml1>
</xml1>
<xml2>
</xml2>
</wrap>
You can use the System.Xml reference, which includes a lot of built-in functionality, and it allows you to declare an XmlTextReader. More info here.
If this is an error log with individual well formed xml elements, you probably don't want to load it as an XMLDocument. A better option is to use an XPathDocument created with an XmlReader where the XmlReaderSettings specify ConformanceLevel.Fragment. Then you can use an XPathNavigator to access your elements and attributes as needed. See the third answer in this forum post for sample code.
...late by just a year and then some. :)

Declare namespaces within XPath expression

My application needs to evaluate XPath expression against some XML data. Expression is provided by user at runtime. So, I cannot create XmlNamespaceManager to pass to XPathEvaluate because I don't know prefixes and namespaces at compile time.
Is there any possibility to specify namespaces declaration within xpath expression?
Answers to comments:
XML data has one default namespace but there can be nested elements with any namespaces. User knows namespaces of the data he works with.
User-provided xpath expression is to be evaluated against many XML documents, and every document can have its own prefixes for the same namespaces.
If the same prefix can be bound to different namespaces and prefixes aren't known in advance, then the only pure XPath way to specify such expressions is to use this form of referring to elements:
someName[namespace-uri() = 'exactNamespace']
So, a particular XPath expression would be:
/*/a[namespace-uri() = 'defaultNS']/b[namespace-uri() = 'NSB']
/c[namespace-uri() = 'defaultNS']
I don't know any way to define a namespace prefix in an XPath expression.
But you can write the XPath expression to be agnostic of namespace-prefixes by using local-name() and namespace-uri() functions where appropriate.
Or if you know the XML-namespaces in advance, you can register an arbitrary prefix for them in the XmlNamespaceManager and tell your user to use that prefix in the XPath expression. It doesn't matter if the XML document itself registers a different prefix or no prefix at all. Path resolution is based on the namespace alone, not on the prefix.
Another option would be to scan the document at runtime (use XmlReader for low resource overhead if you haven't loaded it already) and then add the used mappings in the document in the XmlNamespaceManager. I'm not sure if you can get the namespaces and prefixes from XmlDocument, but I see no direct method to do it. It's easy with XmlReader though, since it exposes NamespaceURI and Prefix members for each node.
Is there any possibility to specify namespaces declaration within xpath expression?
The answer is no - it's always done in the calling environment (which is actually more flexible).
An alternative would be to use XQuery, which does allow declaring namespaces in the query prolog.
UPDATE (2020)
In XPath 3.1 you can use the syntax /*/Q{http://my-namespace}a.
Sadly, though, if you're still using Microsoft software, then the situation hasn't changed since 2011 - you're still stuck with XPath 1.0 with all its shortcomings.

How to embed HTML produced by C# code in XSL?

I have XSLT that creates HTML from XML. There are several parts of the resulting HTML that I need to create by external C# method (extension method).
How do I embed this C# method into XSLT (within what xsl nodes? I do know how to use common extension functions inside XSLT)
What should my C# function return? HTML-formatted string? With escaped HTML tags or without?
Thank you very much!
Well if you want to return HTML tag soup not conforming to XML rules then you can only return a string and then use e.g. <xsl:value-of select="pf:yourFunction()" disable-output-escaping="yes"/>. If you want to build a node-set of nodes or a result tree fragment then check the documentation, it shows the mapping between the XSLT types and the .NET framework types e.g. if you want your function to return an result that XSLT sees as a node-set then use the type XPathNodeIterator as the .NET return type of your extension function.

Categories