How to read a parameter passed by maven on my stylesheet XSL? - maven

I'm running this command:
mvn org.codehaus.mojo:xml-maven-plugin:transform "-DAPP=testingapp"
And inside my XSL I'm transforming a graphml to a HTML and I want to display this app name on the top of my HTML.
How do I read this attribute that I'm passing on the command line on my xsl?
Thank you!

Yes. It is possible.
In your pom.xml
<configuration>
<transformationSets>
<transformationSet>
<parameters>
<parameter>
<name>APP</name>
<value>${APP}</value>
</parameter>
</parameters>
</transformationSet>
</transformationSets>
</configuration>
In your xsl file
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:param name="APP" />
<xsl:value-of select="$APP"/>
</xsl:stylesheet>
You will need to declare in pom.xml and repeat in your xsl file. This is the trick.
Note: This also work for xslt-2.0

Related

I want to read a file which is in datapower through api gateway v10

I'm using url-open() function but I'm getting an empty response.
Something like this should work. You don't need to do urlopen if you are running the code from the same appliance.
<!-- Load config file -->
<xsl:variable name="configFile" select="document('local:///myfolder/servers.xml')" />
<!-- Look in the XML file to find your server -->
<xsl:variable name="myURL">
<xsl:copy-of select="$configFile/config/Servers/Server[#name='prod']/url" />
</xsl:variable>
<?xml version="1.0" encoding="utf-8"?>
<config>
<Servers>
<Server name="prod">
<url>www.google.com</url>
</Server>
<Server name="dev">
<url>www.yahoo.com</url>
</Server>
</Servers>
</config>

Nokogiri XSLT can transform with invalid stylesheet

If I try to transform sample xml (target.xml)
<?xml version="1.0"?>
<root />
with invalid XSL stylesheet (invalid.xsl):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:template match="/root">
<new-root />
</xsl:stylesheet>
</xsl:template>
using Nokogiri (1.6.8.1) ruby v2.1.9:
require 'nokogiri'
print Nokogiri::XSLT(File.open('invalid.xsl'))
.transform(Nokogiri::XML(File.open('target.xml')))
it will finish successfully:
# ruby program.rb
<?xml version="1.0"?>
<new-root xmlns="http://www.w3.org/1999/xhtml"/>
How to configure nokogiri to validate XSL and throw an error if it's invalid?

Access specific appsettings key in Url Rewrite rules

I am trying to access AppSettings Key in the Url Rewrite rules and I am not sure how to access them. Can anyone help me out?
<appSettings>
<add key="APIUrl" value="https://www.x.com/api/{R:1}" />
</appSettings>
<system.webServer>
<rewrite>
<rules>
<rule name="ProxyApi" stopProcessing="true">
<match url="^api/?(.*)" />
<serverVariables>
<set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
<set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" />
</serverVariables>
<action type="Rewrite" url="{APIUrl}" />
</rule>
</rules>
</rewrite>
</system.webServer>
Trying to access the APIUrl key in the UrlRewrite Rule
I think that appsettings are unavailable elsewhere in your config files.
I've found two ways to address this issue using msbuild:
Use xmlupdate task from MSBuild Community Tasks Project to update config files. My work was using this already so it was the path that I took. Would look Like:
<XmlUpdate
XPath="//rule[#name='ProxyApi']/action/#url"
XmlFileName="{Your Config File Location}"
Value="https://www.x.com/api/{R:1}" />
Use XslTransformation Task to update your config files. This solution is built in but requires more knowledge of XSL. The Xsl would looke something like:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//rule[#name='ProxyApi']/action/#url">
<xsl:attribute name="url">
<xsl:value-of select="'https://www.x.com/api/{R:1}'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

Deepest match first with XPath

I have a configuration file in xml, with increasing specificity. That is, the closest setting to some section is the setting that will be in effect, even if it is set on higher levels. A colleague suggested using XPath for this. But I'm not sure how it would work? I suppose I want to find the "deepest match" for the setting, then automatically backing out if there is no match.
For instance:
<Settings>
<Foo>Bar</Foo>
<Products>
<Bar>Baz</Bar>
<Product Name="Thingamabob">
<Foo>Baz</Foo>
</Product>
<Product Name="Whizbang">
<Bar>Foo</Bar>
</Product>
</Products>
</Settings>
Searching for the Bar setting for Thingamabob should return "Baz", but "Foo" on Whizbang. In the same way, Foo has a value of "Baz" for Thingamabob, but "Bar" on Whizbang.
Can this type of lookup be implemented with XPath?
Searching Foo on Thingamabob can be done like so
//*[#Name='Thingamabob']/ancestor-or-self::*/Foo
But this will give you two nodes, you want to obtain the node with the maximum count(ancestor::*) and then get its text() value
I don't know of a way to do max on a xml hierarchy like yours, use an external script to iterate over the node list given by the xpath to find the max depth, then grab its content.
EDIT:
You may be able to do this in XSLT 2.0, note I have not tested this.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:function name="my:lookup">
<xsl:param name="name"/>
<xsl:param name="arg"/>
<xsl:for-each select="//*[#Name='$name']/ancestor-or-self::*/$arg">
<xsl:sort select="count(ancestor::*)" data-type="number" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="."/></xsl:if>
</xsl:for-each>
</xsl:function>
<xsl:template match="/">
<xsl:copy-of select="my:lookup('Thingamabob','Foo')" />
</xsl:template>
</xsl:stylesheet>
EDIT 2:
I've also figure this should work in XPATH 2.0 but I've not tested it
//*[#Name='Thingamabob']/ancestor-or-self::*/Foo[count(ancestor::*) >= //*[#Name='Thingamabob']/ancestor-or-self::*/Foo/count(ancestor::*)]/text()
If you know for certain that <Bar> will precede <Product>, you could do it with this:
//Product[#Name='Thingamabob']/preceding-sibling::Bar|//Product[#Name='Thingamabob']/Bar

How do I use XPath to count the number of nodes with a certain attribute

I can't seem to get an XPath expression to work for my scenario. I want to find all the "Device" nodes that have the type "EndDevice". I'm able to count all the "Device" nodes, and I'm also able to find all "Device" nodes with the "EndDevice" attribute. However, I can't seem to combine them!
count(//Device) //works
//Device[#xsi:type='EndDevice'] //works
count(//Device[#xsi:type='EndDevice']) //doesn't work
If it matters, I'm using XPathBuilder.
I reproduced it using XPathBuilder 2.0.0.4.
However the XPath expression works and evaluates correctly in an online evaluator I tried (http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm).
EDIT: Also tried with latest version of Altova XMLspy
input:
<?xml version="1.0"?>
<asdf xmlns:xsi="n/a">
<Device xsi:type='EndDevice'/>
<Device xsi:type='EndDevice'/>
<Device xsi:type='EndDevice'/>
<Device xsi:type='EndDevice'/>
</asdf>
xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xsi="n/a">
<xsl:output indent="yes"/>
<xsl:template match="*">
<output>
<xsl:value-of select="count(//Device[#xsi:type = 'EndDevice'])"/>
</output>
</xsl:template>
</xsl:stylesheet>
output:
<?xml version="1.0" encoding="UTF-8"?>
<output xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xsi="n/a">4</output>
I think it's XPathBuilder thats doing something wrong.
Using the above xml saved into a test.xml and using the tool http://kernowforsaxon.sourceforge.net/
declare namespace xsi="n/a";
count(doc('test.xml')//Device[#xsi:type = "EndDevice"])
Produces the right output.

Resources