In XSLT/XPath, how do I get the first attribute that doesn't match a specific name? - xslt

I have this snippet of XSLT code:
<xsl:variable name="key" select="#*[1]"/>
But I need it to actually set key to be the first attribute (if it exists) that doesn't have a special name. So both of these nodes would have the same key, and special_attr is ignored if it exists.
<MyNode var="1" />
<MyNode special_attr="foo" var="1" />
What is the proper select syntax to get the first attribute's value whose name isn't special_attr?

<xsl:variable name="key" select="#*[not(name() = 'special_attr')][1]"/>

Related

Unable to get the value of 'xml:lang' attribute

<xoe:documents xmlns:xoe="http://xxxxxx" count="1">
<xocs:doc xmlns:xocs="xxxxxx" xmlns:xsi="yyyyyyy" xsi:schemaLocation="zzzzzz">
<xocs:meta>...</xocs:meta>
<xocs:serial-item>
<!-- this line -->
<article xmlns:sa="www.google.hgy" xmlns="http://www.xyzq1.org/xml/ja/dtd" version="5.4" xml:lang="pl" docsubtype="rev">
<article-info>
</article-info>
</article>
</xocs:serial-item>
</xocs:doc>
</xoe:documents>
I am unable to get the value of 'xml:lang' attribute. Even thought I tried with the below xpath
<xsl:variable name="rootPath" select="/xoe:documents/xocs:doc/xocs:serial-item"/>
<xsl:variable name="lang" select="$rootPath/ja:article[#xml:lang]"/>
or
<xsl:variable name="lang" select="$rootPath/ja:article/#xml:lang"/>
here ja is already defined in my xslt code
xmlns:ja="http://www.xyzq1.org/xml/ja/dtd"
Can some one please help?
First, you need to declare these:
xmlns:xoe="http://xxxxxx"
xmlns:xocs="xxxxxx"
xmlns:ya="www.yahoo.mkt"
Then you can get the value of the xml:lang attribute using:
<xsl:value-of select="/xoe:documents/xocs:doc/xocs:serial-item/ya:article/#xml:lang"/>
Note that the URIs in your stylesheet namespace declarations must be the same URIs that appear in your source XML. The prefixes can be anything you like.

Scope (root node, context) of XSLT "key" Element

I have an XSLT key defined. I need to access the key from within a for-each loop, where that loop is processing a node-set that is outside the scope of where the key was defined.
Snippet, where I've marked two lines, one which works and one which does not:
<xsl:value-of select="key('name', 'use')"/> <!-- works -->
<xsl:for-each select="$outOfScopeNodeSet">
<xsl:value-of select="key('name', 'use')"/> <!-- does not work -->
</xsl:for-each>
Is there a way to access the key from within the for-each loop?
XSLT 1.0, msxsl engine.
(I could not think of a reasonable way to provide a full working example for this. I'm also not sure of the correct terminology, such as "scope" - perhaps if I knew the correct terminology I'd be able to find my answer already. If the question is not clear enough please let me know and I'll try to edit it into better shape.)
In XSLT 1.0, keys do not work across documents. It seems that your $outOfScopeNodeSet contains a node-set whose root node is different from the root node of the XML document being processed (probably created by the exsl:node-set() function?) - while the key is supposed to fetch a value from the processed XML document.
To resolve this problem, you need to return the context back to the processed XML document before calling the key() function, for example:
<xsl:variable name="root" select="/" />
<xsl:for-each select="$outOfScopeNodeSet">
<xsl:variable name="use" select="some-value" />
<xsl:for-each select="$root">
<xsl:value-of select="key('name', $use)"/>
</xsl:for-each>
</xsl:for-each>

Retrieving sub-element attribute's value based on uniq-key with xslt ant

My xml looks something like this:
<someRoot
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../my.xsd">
<position name="quality">
<db>
<server name="blah-blah" type="xyz"/>
</db>
<some-more-element value="12345"/>
<my-needy-element>
<my-needy-sub-element name="uk1"
value="a,b,c"
more-attr="some-val"/>
<my-needy-sub-element name="uk2"
value="x,b,y,c"
more-attr="some-diff-val"/>
</my-needy-element>
</position>
</someRoot>
Retrieving say my single db-server name works after I do xmlproperty & samy something like : ${db.server(name)}. Now I am trying to retrieve value for sub elements - but it always
gives me all row values matching it. eg: ${my-needy-element.my-needy-sub-element(more-attr)} will print some-val,some-diff-val . How do I get attribute value matching
to paricular unique name , something like {my-needy-element.my-needy-sub-element(more-attr) with name="uk1"}
Adding editing comment: Is there any way even if I use xslt ant-task by passing 'uk1' & get required sub-element attribute value? with xsl:if or key match
Amending more:
Have tried with xsl & then an xslt ant , but it doesnot seem to give what I am looking for:
<xsl:template match="/someRoot/my-needy-element/my-needy-sub-element">
<someRoot>
<xsl:key name="my-needy-sub-element" match="text()" use="#name"/>
<xsl:apply-templates select="key('name',$xslParamPassed)"/>
</someRoot>
</xsl:template>
thanks,
You can't do this with xmlproperty but you might consider the third-party xmltask which lets you use full-fledged XPath expressions:
<xmltask source="file.xml">
<copy path="/someRoot/position/my-needy-element/my-needy-sub-element[#name='uk1']/#more-attr"
property="more.attr" />
</xmltask>
<echo>${more.attr}</echo>

Using a parameter passed into xslt stylesheet

I am using Saxon to perform a transformation of an XML document in my .NET application. I am passing in a parameter to my xslt document but I have no idea how to use it in my template.
Here is what I have done so far:
var zipcode = _db.AXCustomers.FirstOrDefault(x => x.ACCOUNTNUM == accNo).ZIPCODE;
transformer.SetParameter(new QName("CustomerZipCode"), new XdmAtomicValue(zipcode));
Then in my xslt document I am specifying the parameter like so:
<xsl:template match="/">
<xsl:param name="CustomerZipCode" />
But when I try to use the parameter, nothing appears. I am using it like so:
<xsl:value-of select="substring-before($CustomerZipCode, ' ')"/>
But nothing is output even though my zipcode does contain a value
You are using xsl:param inside a xsl:template element, it means that the param is for the template. The parameter you are passing from the .net code is a transformer parameter and related xsl:param must be placed at the top level of the stylesheet, into the xsl:stylesheet element.

XSLT parameter is always empty <xsl:param name="mediaFolderId" select="/macro/mediaFolderId" />

I created an xslt called GraphicsRowSlider with the following parameters
<xsl:param name="mediaFolderId" select="/macro/mediaFolderId" />
<xsl:param name="title" select="/macro/title" />
And added the parameters title and mediaFolderId to the related macro.
I then created new Macro Container data type and selected the macro GraphicsRowSlider as allowed macro. I then added a new field of the new data type into a document type and then imported that field into a template.
Finally, from the content, I inserted the macro and added a title and selected media folder... However, I could see that the macro calls the correct xslt with the correct title and mediaFolderId but the parameters are always empty!
Any thought?! Note, I always get this
<?UMBRACO_MACRO macroalias="GraphicsRowSlider" title="Add Title here" mediaFolderId="1159" />
The syntax you are using suggests that you are using an old umbraco version, which one are you using?
The definition how to work with macro parameters can be found on the umbraco wiki: http://our.umbraco.org/wiki/reference/templates/umbracomacro-element/macro-parameters
hth
Your input is an attribute (at least your xml example suggests this) so your xpath should look like this:
<xsl:param name="mediaFolderId" select="/macro/#mediaFolderId" />
<xsl:param name="title" select="/macro/#title" />