I have an XML file that looks like this:
<bases>
<marker>
<name>whatever</name>
<city>Svetly</city>
<country>Kaliningrad</country>
</marker>
<marker>
<name>whatever</nane>
<city>Boston</city>
<country>US</country>
</marker>
<marker>
<name>whatever</nane>
<city>Moscow</city>
<country>Russia</country>
</marker>
</bases>
This XSL allows me to do a selective copy - in this case where the country equals Russia.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Remove all marker elements where country not 'Russia' -->
<xsl:template match="marker[not(country='Russia')]"/>
<!-- Identity template -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I'd like to implement an OR condition, such as where country equals Russia OR Kaliningrad but I can't figure out the syntax. This doesn't work:
<xsl:template match="marker[not(country='Russia|Kaliningrad')]"/>
In XSLT 2 or 3: <xsl:template match="marker[not(country=('Russia', 'Kaliningrad'))]"/>. In XSLT 1: <xsl:template match="marker[not(country='Russia' or country = 'Kaliningrad')]"/>
Related
I am completely clueless trying to change the value of card number for all records to 0 (zero)
The default transform file looks like the following:
<?xml version ="1.0" encoding="utf8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<!-- Parameters assigned at runtime. -->
<xsl:param name="paramCurrentTimestamp">20001231173010</xsl:param>
<xsl:param name="paramCurrentDT" >12/31/2000 5:30:10 PM</xsl:param>
<xsl:param name="paramCurrentCulture">en-US</xsl:param>
<!-- The transformation below provides trivial default copy of everything. -->
<xsl:template match="*|#*">
<xsl:copy>
<xsl:apply-templates select="*|#*|text()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*">
<xsl:copy />
</xsl:template>
<!-- End of customizable area. -->
</xsl:stylesheet>
The sample data input looks like:
Sample input
-<CrossFire culture-info=" en-US" platform-version=" 2.60.18" product-version=" 2.60.18">
-<SoftwareHouse.NextGen.Common.SecurityObjects.Personnel ImportMode=" Default">
<GUID>e7d37b37-9418-4e20-a6b7-f54b76c389cd</GUID>
-<SoftwareHouse.NextGen.Common.SecurityObjects.Credential ImportMode=" Default">
<GUID>e3adb09c-fb8e-4277-90d8-1839dd1bd83b</GUID>
<CardNumber>210316</CardNumber>
</SoftwareHouse.NextGen.Common.SecurityObjects.Credential>
</SoftwareHouse.NextGen.Common.SecurityObjects.Personnel>
</CrossFire>
What I want to see for all of the records is 0
In order to change the value of CardNumber to 0 while keeping everything else as is, you can do simply:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CardNumber">
<xsl:copy>0</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input :
<img xlink:href="figure_one"><?isoimg-id 9324-098_kr1figure1.JPG?></img>
I want to filter out as .jpg part from above input using XSLT. I have no idea to how can I filter out it.
You could simply remove the file extension (regardless of what it is) by using the substring-before() function:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="processing-instruction('isoimg-id')">
<xsl:processing-instruction name="isoimg-id">
<xsl:value-of select="substring-before(., '.')" />
</xsl:processing-instruction>
</xsl:template>
</xsl:stylesheet>
I want to remove specific values from my XML but keep the tag names. I've seen examples that do the opposite (remove tags but keep values). Here is my XML:
<Result>
<Max>100</Max>
<Min>10</Min>
<Range>90</Range>
<ResultPoints>
<ResultP1>.</ResultP1>
<ResultP2>.</ResultP2>
<ResultP3>.</ResultP3>
<ResultP4>.</ResultP4>
<ResultP5>.</ResultP5>
</ResultPoints>
</Result>
I want to remove the '.' but keep the tag names so my XML will look like this:
<Result>
<Max>100</Max>
<Min>10</Min>
<Range>90</Range>
<ResultPoints>
<ResultP1/>
<ResultP2/>
<ResultP3/>
<ResultP4/>
<ResultP5/>
</ResultPoints>
</Result>
Here is my XLT. This completely removes the ResultPn tags.
<?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" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[. = '.']">
<xsl:value-of select="''"/>
</xsl:template>
</xsl:stylesheet>
Any Help will be appreciated!
You just need to do an xsl:copy in your template, to copy across the element you have matched. Note you don't really need to output an empty string here either.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[. = '.']">
<xsl:copy>
<xsl:apply-templates select="#*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note, I added an xsl:apply-templates to copy across any existing attributes.
Alternatively, you could replace the second template with this one instead (which matches the text node directly, rather than the parent element)
<xsl:template match="text()[. = '.']" />
I am new to XSLT and i am trying to accomplish the follow case
I have an xml in the following format
<A>
<B>..</B>
<C>..</C>
..
<Z>..</Z>
</A>
I am trying to add a new node soon after so that the final xml will get transformed to
<A>
<aa>
<B>..</B>
<C>..</C>
..
<X>...</X>
</aa>
</A>
In order to achieve this i wrote the following xslt code
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="B">
<aa>
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</aa>
</xsl:template>
By using this i get the following output
<A>
<aa>
<B>..</B>
</aa>
<C>..</C>
..
<X>..</X>
</A>
I am not sure what kind of changes i need to make to the xslt to achieve the desired output
If you want to wrap all the children of A in a single aa then you need to do that in a template matching A, not B.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="A">
<xsl:copy><!-- copy the A -->
<xsl:apply-templates select="#*" /><!-- attributes, if any -->
<aa><!-- insert the extra aa -->
<xsl:apply-templates /><!-- process children -->
</aa>
</xsl:copy>
</xsl:template>
<!-- this may be a typo in the question, but for reference, here's how
to rename Z to X. If you don't need to do this, just leave this template
out and let the identity template at the top handle it. -->
<xsl:template match="Z">
<X>
<xsl:apply-templates select="#*|node()"/>
</X>
</xsl:template>
</xsl:stylesheet>
hoping this hasn't been asked before, but I have the following XML:
<Company id="1000" name="Company1000">
<Company id="1020" name="Company1020" />
<Company id="1004" name="Company1004">
<Company id="1005" name="Company1005" />
</Company>
<Company id="1022" name="Company1022" />
</Company>
I have the following XPath to search for nodes: //*[contains(translate(#name, "ABCDEFGHJIKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "005")]
I would like this to return:
<Company id="1000" name="Company1000">
<Company id="1004" name="Company1004">
<Company id="1005" name="Company1005" />
</Company>
</Company>
So this matches the Company1005 node, and all its respective parents. I would like the above to also be returned if I were searching for "100", which in that case, would match each element in turn, but I clearly don't want duplication of nodes.
I've been struggling with this for hours now, so your help will be much appreciated!!!
Thanks.
The solution is to copy only descendant or self nodes which match your requirement (containing the string you want).
Look this picture at the bottom of this page for the XPath axes you need.
Long version:
<?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" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Default: copy everything -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- just copy Company which descendant-or-self contain the matching string -->
<xsl:template match="Company">
<xsl:if test="descendant-or-self::Company[contains(translate(#name, 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '005')]">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Short version:
<?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" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Default: copy everything -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- do not copy Company which do not have a descendant-or-self matching string -->
<xsl:template match="Company[not(descendant-or-self::Company[contains(translate(#name, 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '005')])]"/>
</xsl:stylesheet>
Output of your xml:
<?xml version="1.0" encoding="UTF-8"?>
<Company id="1000" name="Company1000">
<Company id="1004" name="Company1004">
<Company id="1005" name="Company1005"/>
</Company>
</Company>