I am using xslt to transform xml to xml with c#. Below is an extract from the xslt where variables assignment is being shown.
<xsl:variable name="testvar">
<xsl:choose>
<xsl:when test="$condition">
<xsl:value-of select="myUtils:Method1($var1,$var2)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="myUtils:Method2($var1,$var2)" /> <!--Method1 and Method 2 are written in c# code.-->
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
The above assignment is different from the below assignment:
<xsl:variable name="testvar" select="myUtils:Method1($var1,$var2)"/>
Another variable depends on the above variable as below:
<xsl:variable name="testvar2" select="$testvar/node()[1]/node()[1]/node()[1]/node()[1]"/>
This variable is assigned the expected value when $testvar is assigned in the second way.
The return type of both Method1 and Method2 is XmlDocument. I think there is something wrong with <xsl:value-of>. What is the correct way of assigning this variable?
UPDATE
I have solved the issue by the following code:
<xsl:variable name="testvar"><xsl:copy-of select="myUtils:Method1($var1,$var2)"/></variable>
For the second variable I have used the below code:
<xsl:variable name="testvar2" select="msxsl:node-set($testvar)/node()[1]/node()[1]/node()[1]/node()[1]"/>
Please refer to this link for more details.
I am guessing your Method1 functions returns node-set, as opposed to simple text/number value. In this this case the issue is probably because xsl:value-of gets the "value" of a node, not the actual node itself.
Try using xsl:copy-of instead
<xsl:copy-of select="myUtils:Method1($var1,$var2)" />
Related
I have following part of xslt in string format :-
<xsl:if test="TestValue3 and TestValue3 != ''">
<xsl:attribute name = "TestDate" >
<xsl:value-of select = "TestValue3" />
</xsl:attribute>
</xsl:if>
I just want to fetch its attribute name from c# code.
Attribuute Name= TestDate
How can I achieve this?
Use your favourite XML API to load the XSLT and iterate/query the item in question (in this case you would need to look for the owning xsl:if and the condition itself). e.g. you could load it into an XmlDocument or XDocument.
You can use XPath to find the element for XmlDocuments or if you use XDocument you can use LINQ.
Do not attempt to use technologies that are not equipped for structured data.
i.e.
don't use flat string search
don't use regex
Actually I am adding above block into existing xslt ,, but before adding I need to check if attribute name =TestDate already exists ... For that I need to know attribute name , becase attribute name can vary as per block,, it is not fix each time
Again, use the above recommendations. Both XmlDocument and XDocument allow for load/edit/save.
If I understand you correctly this should do the job, otherwise please add more context.
<xsl:if test="TestValue3 and TestValue3 != ''">
<xsl:if test="not(#TestDate)">
<xsl:attribute name = "TestDate" >
<xsl:value-of select = "TestValue3" />
</xsl:attribute>
</xsl:if>
</xsl:if>
I know it's been asked numerous times and while my question might seem to be a duplicate, I can't make the list of solutions work.
How come that doesn't seem to add "\r\n" or CRLF in my output file ?
<xsl:variable name="Newline">
</xsl:variable>
...
<xsl:text>UpperLine</xsl:text>
<xsl:value-of select="$Newline"/>
<xsl:text>LowerLine</xsl:text>
Even when looking a tthe hexadcimal representation of the file, I can't see the 0d0a equivalent of CRLF (I can only see the ones at the end)
I've also tried this with no success either :
<xsl:value-of select="concat('New Line', '
')"/>
change your variable declaration to this:
<xsl:variable name="Newline"><xsl:text>
</xsl:text></xsl:variable>
I need to transform an existing XML into another XML using XSLT.
The problem I am facing is that I need to use the "typeName" attribute from the ECClass and concatenate it with http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1#
The XML i am working with is -
<ECSchema>
<ECClass typeName="ABC">
<BaseClass>PQR</BaseClass>
<BaseClass>XYZ</BaseClass>
</ECClass>
<ECClass typeName="IJK">
<BaseClass>MNO</BaseClass>
<BaseClass>DEF</BaseClass>
</ECClass>
<ECSchema>
For example the concatenated result should be -
http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1#ABC for the first ECClass
I need to set this string as the attribute value of rdf:about in the owl:class tag in the new XML structure.
The new XML structure is -
<owl:ontology rdf:about="http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1">
<owl:class rdf:about="http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1#ABC">
</owl:class>
<owl:class rdf:about="http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1#ABC">
</owl:class>
</owl:ontology>
Right now I have not yet tried to do anything about the BaseClass. I have only been trying to convert the ECCLass to owl:class.
The XSL for it is -
<xsl:template match="/">
<owl:Ontology rdf:about="http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1"/>
<xsl:for-each select="ECSchema/ECClass">
<owl:class rdf:about="<xsl:value-of select="concat('http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1#' , '#typeName') />" >
</owl:class>
</xsl:for-each>
</xsl:template>
I have been trying many combinations to do this from various sources but haven't been able to do it.
It always returns an error - "Additional information: '<', hexadecimal value 0x3C, is an invalid attribute character."
Can anybody please help me with this as I am very new to XSLT and all I have been getting is lots of errors.
Tags cannot be nested. To achieve your purpose, you should learn about attribute value templates. In addition, your code is rather sloppy. Try it this way:
<xsl:template match="/">
<owl:Ontology rdf:about="http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1">
<xsl:for-each select="ECSchema/ECClass">
<owl:class rdf:about="{concat('http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1#', #typeName)}" />
</xsl:for-each>
</owl:Ontology>
</xsl:template>
or perhaps a bit more elegant:
<xsl:variable name="myURL">http://www.semanticweb.org/aman.prasad/ontologies/2015/5/untitled-ontology-1</xsl:variable>
<xsl:template match="/">
<owl:Ontology rdf:about="{$myURL}">
<xsl:for-each select="ECSchema/ECClass">
<owl:class rdf:about="{$myURL}#{#typeName}" />
</xsl:for-each>
</owl:Ontology>
</xsl:template>
Using a XPath query how do you find if a node (tag) exists at all?
For example if I needed to make sure a website page has the correct basic structure like /html/body and /html/head/title.
<xsl:if test="xpath-expression">...</xsl:if>
so for example
<xsl:if test="/html/body">body node exists</xsl:if>
<xsl:if test="not(/html/body)">body node missing</xsl:if>
Try the following expression: boolean(path-to-node)
Patrick is correct, both in the use of the xsl:if, and in the syntax for checking for the existence of a node. However, as Patrick's response implies, there is no xsl equivalent to if-then-else, so if you are looking for something more like an if-then-else, you're normally better off using xsl:choose and xsl:otherwise. So, Patrick's example syntax will work, but this is an alternative:
<xsl:choose>
<xsl:when test="/html/body">body node exists</xsl:when>
<xsl:otherwise>body node missing</xsl:otherwise>
</xsl:choose>
Might be better to use a choice, don't have to type (or possibly mistype) your expressions more than once, and allows you to follow additional different behaviors.
I very often use count(/html/body) = 0, as the specific number of nodes is more interesting than the set. For example... when there is unexpectedly more than 1 node that matches your expression.
<xsl:choose>
<xsl:when test="/html/body">
<!-- Found the node(s) -->
</xsl:when>
<!-- more xsl:when here, if needed -->
<xsl:otherwise>
<!-- No node exists -->
</xsl:otherwise>
</xsl:choose>
I work in Ruby and using Nokogiri I fetch the element and look to see if the result is nil.
require 'nokogiri'
url = "http://somthing.com/resource"
resp = Nokogiri::XML(open(url))
first_name = resp.xpath("/movies/actors/actor[1]/first-name")
puts "first-name not found" if first_name.nil?
A variation when using xpath in Java using count():
int numberofbodies = Integer.parseInt((String) xPath.evaluate("count(/html/body)", doc));
if( numberofbodies==0) {
// body node missing
}
Is there a way to ignore case when we try to use XPathSelectElement or any operation like to retrieving attributes from XDocument? The purpose for asking this question is that, I have some configuration files (xml) and I am writing a generic code that will read the config files to get required information for XPathSelectElement. Also, I try to get the values of attributes. Even if someone puts the nodes/attributes in different case, my program should be able to work without fail.
I use C#/.Net 3.5.
You can't ignore case with XPath. You can accomodate, though.
For example - elements, assuming they contain letters in the ASCII range only:
//*[
translate(
name(),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'
) = 'myname'
]
Attributes would work the same (with #* in place of *).
If you do not want to bloat your XPath expressions with this, you could lower-case all element- and attribute names beforehand, for example via XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(name(), $upper, $lower)}">
<xsl:apply-templates select="node() | #*" />
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{translate(name(), $upper, $lower)}">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Before you load the XML string make lower-case. That will solve the issue. I use this method myself.