0

new to XSLT 1.0 and I really struggle with extracting the values of the following XML (using XSLT1.0):

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
    <smallnote xmlns="http://soap.test.com/2005/ob">
        <Id>1234</Id>
        <Note>
            <Id>4567</Id>
            <sObject xsi:type="abc:Testcase" xmlns:abc="urn:soap.test.com">
                <abc:Id>890</abc:Id>
                <abc:Name>Some name</abc:Name>
            </sObject>
        </Note>
    </smallnote>
</soapenv:Body>
</soapenv:Envelope>

Desired output:

        <?xml version="1.0" encoding="UTF-8"?>
        <Id>1234</Id>
        <NoteId>4567</NoteId>
        <ObjType>Testcase</ObjType>
        <ObjId>890</ObjId>
        <ObjName>Some name</ObjName>

How can I deal with the namespace? I know of:

<xsl:value-of select="//*[local-name() = 'Id']" />

but it does not seem to work for me with multiple Id fields.

Is it a better approach to first remove the namespace? Because right now I struggle to select the correct "path" whenever I try to extract the values.

Thanks in advance

  • 2
    See if this helps: https://stackoverflow.com/questions/34758492/xslt-transform-doesnt-work-until-i-remove-root-node/34762628#34762628 -- P.S. Are you sure that's the output you want? With no root element? -- PP.S. If you have multiple ids, then don't use the descendant `//` axis; use an explicit path instead. – michael.hor257k Sep 08 '17 at 12:38

1 Answers1

0

Is it a better approach to first remove the namespace?

I understand your desire for simplicity, but even if it looks cumbersome at the beginning handling namespaces if not as difficult as it may seem to you. Just keep in mind that children with no namespace-prefix inherit the default namespace set by xmlns=... attributes.

Let's walk this through:

  • soapenv:Envelope has the explicit namespace soapenv
  • soapenv:Body too
  • smallnote defines a default namespace for itself and its children.
  • So all children of smallnote use this namespace except for those explicitly defined with the abc namespace, Id and Name.

To exclude the namespaces from the output use the exclude-result-prefixes attribute with the namespace prefixes to get rid of.

So the code could look like this:
(I added a simple root tag aNote to make the output well-formed XML for one tst:smallnote node)

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:tst="http://soap.test.com/2005/ob"  
  xmlns:abc="urn:soap.test.com"
  exclude-result-prefixes="xsi xsd tst abc soapenv">    
    <xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="no"/>

    <xsl:template match="tst:smallnote">
      <aNote>
        <Id><xsl:value-of select="tst:Id" /></Id>
        <NoteId><xsl:value-of select="tst:Note/tst:Id" /></NoteId>
        <ObjType><xsl:value-of select="substring-after(tst:Note/tst:sObject/@xsi:type,':')" /></ObjType>
        <ObjId><xsl:value-of select="tst:Note/tst:sObject/abc:Id" /></ObjId>
        <ObjName><xsl:value-of select="tst:Note/tst:sObject/abc:Name" /></ObjName>
      </aNote>
    </xsl:template>

</xsl:stylesheet>

Output is:

<?xml version="1.0" encoding="UTF-8"?>    
<aNote>
    <Id>1234</Id>
    <NoteId>4567</NoteId>
    <ObjType>Testcase</ObjType>
    <ObjId>890</ObjId>
    <ObjName>Some name</ObjName>
</aNote>
zx485
  • 28,498
  • 28
  • 50
  • 59