I have an xsl transformation to generate ASP.NET User controls (ascx).
My XSL is defined this way:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:asp="System.Web.UI.WebControls"
exclude-result-prefixes="asp msxsl"
>
<xsl:output method="xml" indent="no" omit-xml-declaration="yes" />
So from that exclude-result-prefixes I would assume, that everything with the asp prefix should not add the namespace information, but i.e. this template here:
<xsl:template match="Label">
<asp:Label runat="server" AssociatedControlID="{../#id}">
<xsl:copy-of select="./text()"/>
</asp:Label>
</xsl:template>
fed with this xml:
<Label>Label Text</Label>
results in this output:
<asp:Label runat="server" AssociatedControlID="SomeName" xmlns:asp="System.Web.UI.WebControls">Label Text</asp:Label>
So what do I need to do to prevent the xmlns:asp=".." to show up in every single tag in my result?
It is impossible, at least in MSXML, that is because output XML won't be well-formed. You can only output it like text, e.g. using CDATA.
Related
I came across situation where XML tag has HTML code that needs to be parsed in XSLT. Here is the XML sample:
<note>
<text><p>This is a paragraph.</p><p>This is another paragraph.</p></text>
</note>
I want the embedded paragraph elements to be stored in different variables.
This is a paragraph. should be stored in one variable and This is another paragraph. should be stored in another variable.
Can you please help?
Parsing XML documents with parse-xml https://www.w3.org/TR/xpath-functions/#func-parse-xml or XML fragments with parse-xml-fragment https://www.w3.org/TR/xpath-functions/#func-parse-xml-fragment is supported in XSLT 3.0, in earlier versions you would have to rely on processor specific extension provided or implementable.
Your escaped code looks like an XHTML fragment so it should be parseable with parse-xml-fragment as in https://xsltfiddle.liberty-development.net/bFDb2CQ which does
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="text">
<div>
<xsl:variable name="contents" select="parse-xml-fragment(.)"/>
<xsl:variable name="p1" select="$contents/p[1]"/>
<xsl:variable name="p2" select="$contents/p[2]"/>
<xsl:sequence select="$p1, $p2"/>
</div>
</xsl:template>
</xsl:stylesheet>
I want to know if there's any url logic if url contains /market/3. like:
<xsl:variable name="cultureRequest" select="concat('http://',MAIN_URL)" />
<xsl:if test="contains($cultureRequest, '/market/3')" >
</xsl:if>
well, there's any way to check if url contains /market/3/ for example?
As I said in the comments, yes, that's possible. As long as the URL is a string. But you have to be aware that this does not mean that XSLT treats this string as an URL. It still thinks of it as a string.
For example, your code snippet works with the following input:
<?xml version="1.0" encoding="UTF-8"?>
<MAIN_URL>www.main-url.com/market/3/xs.htm</MAIN_URL>
Then, you could apply a stylesheet like the one below. It outputs a yes element if the contains function returns true.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:variable name="cultureRequest" select="concat('http://',MAIN_URL)" />
<xsl:if test="contains($cultureRequest, '/market/3')" >
<yes>!</yes>
</xsl:if>
</xsl:template>
</xsl:transform>
XML Output
The URL contains /market/3, so the output is:
<?xml version="1.0" encoding="UTF-8"?>
<yes>!</yes>
Note: There are two things I did not understand about your question and that I tried to ask about in the comments:
I am not sure why you concatenate the URL to http;// before handing
it to contains.
Why do you refer to "url logic"?
I have the following xml and want the output to not contain the xml declaration
i.e.
FROM
<?xml version="1.0" encoding="UTF-8"?>
<tns:MFTRNS xmlns:tns="MFTRNS" recordState="New" msgVersion="13.0">
<OSCONO>100</OSCONO>
<OSINOU>1</OSINOU>
<OSDLIX>155379</OSDLIX>
<OSPANR>AAG44780</OSPANR>
<OSWHLO>AAG</OSWHLO>
</tns:MFTRNS>
TO
<tns:MFTRNS xmlns:tns="MFTRNS" recordState="New" msgVersion="13.0">
<OSCONO>100</OSCONO>
<OSINOU>1</OSINOU>
<OSDLIX>155379</OSDLIX>
<OSPANR>AAG44780</OSPANR>
<OSWHLO>AAG</OSWHLO>
</tns:MFTRNS>
Can you get an xslt to do this and if so how?
The reason for doing this is that I want to wrap the xml in an envelope which cannot be done if the declaration is a part of the XML as it does not create a valid xml file
Thanks
If you only want to remove the declaration then a stylesheet as simple as this will do it:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:copy-of select="node()" />
</xsl:template>
</xsl:stylesheet>
But if your ultimate aim is to "wrap the xml in an envelope" then you might be better doing that directly in your XSLT, for example:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" />
<xsl:template match="/">
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope">
<xsl:copy-of select="node()" />
</soap:Envelope>
</xsl:template>
</xsl:stylesheet>
which will be safer than trying to combine the two files using non-XML-aware textual operations. For example, if your envelope declares a default namespace xmlns="http://example.com" then simply inserting the text of another XML document inside the envelope would change the semantics as it would move the non-prefixed elements like OSCONO into the envelope's default namespace when they should really be in no namespace. XSLT will spot this case and add the necessary xmlns="" overrides.
It's simple: you have to set the omit-xml-declaration attribute of your xsl:output element to yes.
I'm sure this is a very simple fix, but I'm stumped. I've got input XML with the following root element, and repeating child elements:
<modsCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.loc.gov/mods/v3"
xsi:schemaLocation="
http://www.loc.gov/mods/v3
http://www.loc.gov/standards/mods/v3/mods-3-4.xsd">
<mods version="3.4">
...
I've got an XSLT sheet with the following to match each <mods> node, and kick it out as a separate file named by an <identifier type="local"> element.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.loc.gov/mods/v3">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/modsCollection">
<xsl:for-each select="mods">
<xsl:variable name="filename"
select="concat(normalize-space(
identifier[#type='local']),
'.xml')" />
<xsl:result-document href="{$filename}">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This works if the XML input does not have the xmlns:xsi, xmlns, or xsi:schemaLoaction attributes in the root element. So, for example, it works on the following:
<modsCollection>
<mods version="3.4">
...
I know that some of our MODS files have had the prefix included but I'm unclear why this won't work without the prefix if our XSLT matching is not looking for the prefix. Any thoughts or advice would be greatly appreciated.
<xsl:template match="/modsCollection">
matches modsCollection in no namespace. You want
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.loc.gov/mods/v3"
xmlns:m="http://www.loc.gov/mods/v3">
then
<xsl:template match="/m:modsCollection">
To match modsCollection in the mods namespace, and similarly use the m: prefix in all xslt patterns and xpath expressions in the stylesheet.
Take the below xml
<?xml version="1.0"?>
<?xml-stylesheet href="desktop.xsl" type="text/xsl"?>
<desktop>
<tag name="h1" caption="hello"/>
</desktop>
I have an XSLT that will take the name attribute of the tag element and create the appropriate html element
Snippet from the xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="tag">
<{#name}>{#caption}</{#name}>
</xsl:template>
</xsl:stylesheet>
which of course is not working, due to the < > characters (I suppose)
How can I come around it?
Thanks
You will need to use <xsl:element>. See here.
For example:
<xsl:element name="#name"><xsl:value-of select="#caption"></xsl:element>
Use <xsl:element> instead which will create a new node. For example, I've once used the following code to create automatically nested headings in HTML:
<xsl:variable name="extlevel" select="count(ancestor::External[not(#link)])"/>
<xsl:element name="h{$extlevel + 2}"><xsl:value-of select="#name"/></xsl:element>