Select the string of an XSLT param given at command line - string

I am using XSLT params to set an absolute path in an attribute at runtime using Xalan-C. Basically, my input XML is something like this :-
<root xmlns="initial">
<!-- document goes here -->
</root>
My stylesheet is :-
<xsl:stylesheet version="1.0" xmlns:s="initial" xmlns="final" />
<xsl:param name="default_data_location">/path/to/some/location</xsl:param>
<xsl:template match="//s:*">
<xsl:element name="{local-name()}" namespace="final">
<xsl:attribute name="dataLocation">
<xsl:value-of select="concat($default_data_location, '/datafile')"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
<!-- rest of the stylesheet -->
</xsl:stylesheet>
Thus, my desired output XML when I run it as :-
Xalan foo.xml foo.xsl
should be (this is the part that works) :-
<root xmlns="final" dataLocation="/path/to/some/location/datafile">
<!-- document goes here -->
</root>
And when I run it as :-
Xalan -p default_data_location /some/other/path foo.xml foo.xsl
it should be (and this is the part that doesn't work) :-
<root xmlns="final" dataLocation="/some/other/path/datafile">
<!-- document goes here -->
</root>
If I try to set this param at the command line, however, it gives me the following XML :-
<root xmlns="final" dataLocation="/datafile">
<!-- document goes here -->
</root>
What should I be doing?

The parameter value seems to be an XPath expression so you need to make sure you pass in an XPath string and you might need to double quotes to make sure the command line shell does not get into your way so doing Xalan -p default_data_location "'/some/other/path'" foo.xml foo.xsl should work. At least that's my reading of the documentation at http://xml.apache.org/xalan-c/commandline.html, I don't have Xalan-C to test.

Related

uncomment xml tags on centOS 7.x

Is there a command (using sed or any other tool) to remove XML comment (which has a comment string also) on some XML tags? I am using centos 7.4 and 7.9. The XML structure is like this:
<root>
<!-- Some string here to inform
<SomeTagHere />
<SomeTagHere2> </SomeTagHere2>
-->
</root>
I tried many different sed commands but none of them worked and I couldn't find a proper regex for this. What I want to is release tags inside comment like this:
<root>
<SomeTagHere />
<SomeTagHere2> </SomeTagHere2>
</root>

Update specific value in xml file by bash

I need update specific value in xml in automatic way by bash script.
My xml file has a lot of similar line like:
<xml>
<main>
<buildElement name="test_one" version="" path="" />
<buildElement name="test_two" version="" path="" />
</main>
</xml>
I need find element name "test_one" and edit version.
I am trying this, but it's not help:
Expected output:
<xml>
<main>
<buildElement name="test_one" version="some_value" path="" />
<buildElement name="test_two" version="" path="" />
</main>
</xml>
I am trying get this by xmlstarlet and sed, but is not working f.e:
xmlstarlet edit --update '//xml/main/buildElement/name="test_one"/version' --value 'some_value' myXML.xml
Your xpath syntax is incorrect. You need to use # to refer to attributes, and to search for a particular element you need a filter expression. You want:
xmlstarlet edit --update \
'//xml/main/buildElement[#name="test_one"]/#version' \
-v some_value myXML.xml
Which will output:
<?xml version="1.0"?>
<xml>
<main>
<buildElement name="test_one" version="some_value" path=""/>
<buildElement name="test_two" version="" path=""/>
</main>
</xml>
'//xml/main/buildElement/name="test_one"/version'
You want
'//xml/main/buildElement[#name="test_one"]/#version'
(Basically, you seem to be guessing, and that's not going to get you very far with XPath. Do some reading.)

AWK to replace HTML tag with another and keep text

I am looking for a way to replace a HTML tag with another, but keep the text.
I have a big HTML file, which contains:
<span class="desc e-font-family-cond">fork</span>
I want to replace <span> tag with <strong> tag:
<strong>fork</strong>
Tool doesn't really matter, but I am looking for a CLI way to do it.
I am not looking for a HTML processor, because input is a text file with some HTML code in it (not a clean/valid HTML) and I am manually working with the output (copy, modify, use later in its final place). I just want to save some time with the replace.
I would use GNU sed for this task following way, let file.txt content be
<span class="desc e-font-family-cond">fork</span>
then
sed -e 's/<span[^>]*>/<strong>/g' -e 's/<\/span>/<\/strong>/g' file.txt
output
<strong>fork</strong>
Explanation: firstly replace span starting using <strong>, secondly replace span closing using </strong>.
Consider using Python and a tool like BeautifulSoup to handle HTML. Trying to parse HTML with other tools like sed or awk can lead to terrible places.
As an example:
from bs4 import BeautifulSoup
soup = BeautifulSoup('<li><span class="desc e-font-family-cond">fork</span>')
for spanele in soup.findAll('span'):
spanele.name = 'p'
html_string = str(soup)
print(html_string);
That's lightweight and pretty simple and the html is handled properly with a library that is specifically built to parse it.
Don't use AWK for processing HTML files. If you can turn your HTML file into an XHTML file, you can use xsltproc for an XML transformation as follows:
trans.xsl file:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="span[#class='desc e-font-family-cond']">
<strong><xsl:apply-templates/></strong>
</xsl:template>
</xsl:stylesheet>
CLI command for invoking xsltproc, which has to be installed, obviously:
xsltproc trans.xsl file.html
The standard output of this command is the corrected HTML file as you want to have it.
Using sed:
sed 's,<\(\/\)\?span\(\s\)\?,<\1strong\2,g'
$ echo '<span class="desc e-font-family-cond">fork</span>' | sed 's,<\(\/\)\?span\(\s\)\?,<\1strong\2,g'
<strong class="desc e-font-family-cond">fork</strong>

Write binary file from base64 content

I have base64 encoded contents (image file) and I'd like to write this to an external file using XSLT/XPath 2.0.
This is my input file
<root>
<img>iVBORw0KGgoAAAANSUhEUgAABAAAAAMAAQMAAACAdIdOAAAABlBMVEUAAAD///
+l2Z/dAAABpElEQVR42u3OQQ0AMAgEsHOAf7Wbhn0GIa2C5jSLgICAgICAgICAgI
CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMDgQB6UgICAgICAgICAgICAgI
CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
CAgICAgICAgICAgICAgICAgICAgICAgMDKwB8CAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAu2BC6XQXOr9fnZDAAAAAElFTkSuQmCC</img>
</root>
And this my my attempt to write the file:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:file="http://expath.org/ns/file">
<xsl:template match="img">
<myimg>
<xsl:variable name="filename" select="'hello.png'"/>
<xsl:attribute name="filename" select="$filename"/>
<xsl:value-of select="file:write-binary($filename,xs:base64Binary(.))" />
</myimg>
</xsl:template>
</xsl:stylesheet>
But "nothing happens", which means I get an XML file with myimg as the root tag (expected), but no file written into the current directory. What am I supposed to do?
I use Saxon-PE-9.7.0.15 with oXygen XML
Edit: use hello.png as a filename (to lessen the confusion)
It seems a problem related to using Saxon and the EXPath file module inside oXygen because when I run the XSLT outside oXygen with Saxon the file is created in the same directory as the XML input and stylesheet code, however inside oXygen the use of <xsl:message select="'current-dir() ', file:current-dir()"/> indicates the file module uses a different directory to read from and write to.

shell script sed replace

I have this file config.xml
<widget id="com.example.hello" version="0.0.1">
<name>HelloWorld</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev#callback.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<enter>PASSWORD</enter>
<content src="index.html" />
<access origin="*" />
I tried to do it with sed without success.
I need to do this:
$./script.sh config.xml NEWPASSWORD
to get:
<widget id="com.example.hello" version="0.0.1">
<name>HelloWorld</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev#callback.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<enter>NEWPASSWORD</enter>
<content src="index.html" />
<access origin="*" />
Using backreference:
sed "s/^\( *<enter>\)\([^>]*\)</\1$2</" "$1"
^\( *<enter>\): search for lines starting with any number of spaces followed by <enter>. Matching characters are captured with escaped parentheses.
\([^>]*\)<: following characters up top next < are captured in a second group.
\1$2<: in the substitution string, characters from first group are output(\1) followed by the second parameter value passed to the script, ($2, the new password value)
The command is applied to $1, the file passed as first parameter to the script (the file name).
To edit the file in place, use the -i flag:
sed -i "s/^\( *<enter>\)\([^>]*\)</\1$2</" "$1"
The good result is:
$cat script.sh
#!/bin/sh
file=$1
sed -i "s/^\( *<enter>\)\([^>]*\)</\1$2</" "$1"
Then:
$./script.sh config.xml NEWPASSWORD
Many thanks to everyone, especially to Kenavoz.

Resources