This question already has answers here:
XSLT Transform doesn't work until I remove root node
(2 answers)
Closed 6 years ago.
The below xml is not transforming because of xmlns, I tried without xmlns, it working as expected. but i am receiving input with xmlns. Please suggest how can i overcome it.
Requirement: To retrieve productBenefitHeaders from the xml.
XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<productData xmlns="http://www.example.org/consolidated">
<productResponse>
<product>
<status>
<isError>false</isError>
</status>
<productBenefit>
<productBenefitCategory>CARDs</productBenefitCategory>
<productBenefitId>12AA</productBenefitId>
<productBenefitHeader>Philips</productBenefitHeader>
</productBenefit>
<productBenefit>
<productBenefitCategory>CARDs</productBenefitCategory>
<productBenefitId>12AB</productBenefitId>
<productBenefitHeader>Samsung</productBenefitHeader>
</productBenefit>
</product>
</productResponse>
<productData>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:template match="/">
<xsl:for-each select="productData/productResponse/product/productBenefit">
<xsl:value-of select="productBenefitHeader"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The elements in the source xml are in the namespace http://www.example.org/consolidated. While you are searching for elements without specifying the namespace.
To search with the namespace you need to add the namespace in the stylesheet tag and set a prefix for it, in this case I used 'pref'.
xmlns:pref="http://www.example.org/consolidated"
Now you can use the prefix in your xsl while specifying the elements you are looking for. This is your xsl but with the prefix added.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:pref="http://www.example.org/consolidated">
<xsl:output method="html" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:template match="/">
<xsl:for-each select="pref:productData/pref:productResponse/pref:product/pref:productBenefit">
<xsl:value-of select="pref:productBenefitHeader"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Also, make sure your end tag is correct. Currently the last tag in your example xml is not a closing tag.
Related
I have the following XML with a cdata tag that I would like to extract the text from?
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<cus:TestData xmlns:cus="http://test.namespace.com/data">
<![CDATA[testValue]]></cus:TestData >
How can I achieve this in XSLT?
I was briefly trying with the following
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
"<xsl:value-of select="/*/Name"/>"
</xsl:template>
</xsl:stylesheet>
But it doesn't seem to be working
Also the XML doesn't also have the same prefix or namespace, it changes
This is not really an issue with CData. Your XSLT is currently looking for an element called Name, under the root element, which does not exist in your XML. If your XML source is the one you are actually using, you can just do this...
<xsl:value-of select="/*"/>
But supposing your XML looked like this...
<cus:TestData xmlns:cus="http://test.namespace.com/data">
<cus:Name><![CDATA[testValue]]></cus:Name>
</cus:TestData>
Then, you would need to account for the namespace in your XSLT, as Name is in a namespace in your XML, but your XSLT is currently looking for a Name element in no namespace.
Something like this would do:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:c="http://test.namespace.com/data">
<xsl:output method="text"/>
<xsl:template match="/">
"<xsl:value-of select="/*/c:Name"/>"
</xsl:template>
</xsl:stylesheet>
Note, the prefixes don't need to match, but the namespace URI does.
If the namespace URI could actually vary, you could do something like this instead...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
"<xsl:value-of select="/*/*[local-name() = 'Name']"/>"
</xsl:template>
</xsl:stylesheet>
I have an XML and transforming it using XSLT. But the result transformed xml file containing unnecessary namespces.
UPDATED
How to make the xslt not to have the xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" in the result xml file.
Add the attribute "exclude-result-prefixes" on xsl:stylesheet node and list the namespaces you want to exclude
Sample
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fn="http://www.w3.org/2005/xpath-functions" version="2.0" exclude-result-prefixes="xsl fo xs fn">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="no"/>
<xsl:template match="#*|*|comment()">
<xsl:copy>
<xsl:apply-templates select="#*|*|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Yeah!
Jean-Michel is right, you must use exclude-result-prefixe="soapenv", thats works for me.
This question was aswered here:
How to remove namespace from the output xml?
I am working with xslt to handle the results that are returned from a web service. I first need to determine which web service the results are for. I know that the tag platformCore:record has the attribute "xsi:type="listRel:Contact or "xsi:type="listEmp:Employee". I am trying to select the value that the attribute is storing, but the colon seems to be causing some issues when I attempt to select the value.
Here is what I tried, but fails to work.
<?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" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:variable name="Type"><xsl:value-of select="//*[local-name()='searchResponse']//*[local-name()='searchResult']//*[local-name()='recordList']//*[local-name()='record']#xsi:type"/></xsl:variable>
<root>
<test><xsl:value-of select="$Type"/></test>
</root>
</xsl:template>
</xsl:stylesheet>
Here is a simple sample
<?xml version="1.0" encoding="UTF-8"?>
<searchResponse:searchResponse xmlns="urn:messages_2012_2.platform.webservices.itsthesuite.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:searchResponse="urn:messages_2012_2.platform.webservices.itsthesuite.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<platformCore:searchResult xmlns:platformCore="urn:core_2012_2.platform.webservices.itsthesuite.com">
<platformCore:status isSuccess="true"/>
<platformCore:totalRecords>1</platformCore:totalRecords>
<platformCore:recordList>
<platformCore:record internalId="154098" xsi:type="listRel:Contact" xmlns:listRel="urn:relationships_2012_2.lists.webservices.itsthesuite.com">
<listRel:entityId>John Smith</listRel:entityId>
<listRel:firstName>John</listRel:firstName>
<listRel:lastName>Smith</listRel:lastName>
<listRel:phone>(777) 777-7777</listRel:phone>
<listRel:email>john.smith#yormoms.com</listRel:email>
</platformCore:record>
</platformCore:recordList>
</platformCore:searchResult>
</searchResponse:searchResponse>
I need the solution to work for this sample as well.
Employee Sample
<?xml version="1.0" encoding="UTF-8"?>
<searchResponse xmlns="urn:messages_2012_2.platform.webservices.netsuite.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:searchResponse="urn:messages_2012_2.platform.webservices.netsuite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<platformCore:searchResult xmlns:platformCore="urn:core_2012_2.platform.webservices.netsuite.com" >
<platformCore:status isSuccess="true"/>
<platformCore:totalRecords>1</platformCore:totalRecords>
<platformCore:recordList>
<platformCore:record internalId="158778" xsi:type="listEmp:Employee" xmlns:listEmp="urn:employees_2012_2.lists.webservices.netsuite.com">
<listEmp:entityId>331sfds Dipo Chaponda</listEmp:entityId>
<listEmp:salutation>Mr.</listEmp:salutation>
<listEmp:firstName>Dipo</listEmp:firstName>
<listEmp:lastName>Chaponda</listEmp:lastName>
<listEmp:email>dchapond#youmm.com</listEmp:email>
</platformCore:record>
</platformCore:recordList>
</platformCore:searchResult>
</searchResponse>
You can select an attribute using local name similarly to what you are already doing, but by prefacing the * with an #:
#*[local-name() = 'type']
However, littering your XPaths with local-name() = and double slashes is not a good practice. You should use namespaces properly, and use precise paths when they are known, although it seems that is not an option for the elements in your case because they are using different namespaces in the two examples. This should work:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="sr pc xsi"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:variable name="Type">
<xsl:value-of select="*[local-name() = 'searchResponse']/
*[local-name() = 'searchResult']/
*[local-name() = 'recordList']/
*[local-name() = 'record']/
#xsi:type"/>
</xsl:variable>
<root>
<test>
<xsl:value-of select="$Type"/>
</test>
</root>
</xsl:template>
</xsl:stylesheet>
When run on your sample input, this produces the expected result:
<root>
<test>listRel:Contact</test>
</root>
I have the following xml:
<RootNode xmlns="http://someurl/path/path/path">
<Child1>
<GrandChild1>Value</GrandChild1>
<!-- Lots more elements in here-->
</Child1>
</RootNode>
I have the following xslt:
<xsl:stylesheet version="1.0" xmlns="http://someurl/path/path/path" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="RootNode/Child1">
<NewNodeNameHere>
<xsl:value-of select="GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode >
</xsl:template>
</xsl:stylesheet>
The problem: this is the my result:
<?xml version="1.0" encoding="utf-8"?>
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1 />
</NewRootNode>
I am expecting to see:
<?xml version="1.0" encoding="utf-8"?>
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<NewNodeNameHere>Value</NewNodeNameHere>
<!-- Other new elements with values from the xml file -->
</NewChild1>
</NewRootNode>
I am missing of the information inside of NewChild1 that should be there.
I think my for-each select is correct, so the only thing I can think of is that there is a problem with the namespace in the Xml and the namespace in the xslt. Can anybody see what I'm doing wrong?
The problem is caused by the namespaces.
Since the xml defines xmlns="http://someurl/path/path/path", it is not in the default namespace anymore.
You can define that namespace with an name like xmlns:ns="http://someurl/path/path/path" in the xsl, and then use that name in the XPath expression.
The following works for me:
<xsl:stylesheet version="1.0" xmlns:ns="http://someurl/path/path/path" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="ns:RootNode/ns:Child1">
<NewNodeNameHere>
<xsl:value-of select="ns:GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode >
</xsl:template>
</xsl:stylesheet>
The stylesheet namespace should be http://www.w3.org/1999/XSL/Transform instead of http://someurl/path/path/path.
Also, since the input XML uses a namespace all your XPath expressions should be namespace-qualified:
<xsl:template match="/" xmlns:ns1="http://someurl/path/path/path">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="ns1:RootNode/ns1:Child1">
<NewNodeNameHere>
<xsl:value-of select="ns1:GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode>
</xsl:template>
I am new to XSLT I am trying to transform a name value pair to its corresponding XML. This feature is primarily used in case of special extensions to a standard.
The file I want to transform is the following. There are no spaces expected in any of the extNames.
<?xml version="1.0" encoding="UTF-8"?>
<extensionItems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ExtensionItems.xsd">
<extensionsItem>
<extName> callCode</extName>
<extValue>1</extValue>
<extType>integer</extType>
</extensionsItem>
<extensionsItem>
<extName>callbackType</extName>
<extValue>All</extValue>
<extType>string</extType>
</extensionsItem>
<extensionsItem>
<extName>callbackEmail</extName>
<extValue>me#mine.org</extValue>
<extType>string</extType>
</extensionsItem>
</extensionItems>
to the following:
<ODEventNotificationExtraField>
<callCode> 1</callCode>
<callbackType> All </callbackType>
<callbackEmail> me#mine.org </callbackEmail>
</ODEventNotificationExtraField>
The following stylesheet produces the desired result:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="extensionItems">
<ODEventNotificationExtraField>
<xsl:apply-templates/>
</ODEventNotificationExtraField>
</xsl:template>
<xsl:template match="extensionsItem">
<xsl:element name="{extName}">
<xsl:value-of select="extValue"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>