简体   繁体   中英

XSLT on XML with namespaces not working

I have XML that gets sent off to a third-party vendor as part of a mature feed. The XML is a bit suspect with its usage of namespaces, but I most likely cannot change it at this point since the feed is mature and not to be tinkered with.

I am trying to set up a XSLT template to display the contents of each XML feed as an HTML table. And running into problems.

Below is a simplified version of what I'm trying, selecting just one element. If I can get past whatever I'm missing, I can probably figure out the rest myself.

Partial XML snippet:

<nis:Jobs xmlns:nis="http://schemas.monster.com/Monster/NIS" xmlns="http://schemas.monster.com/Monster" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.monster.com/Monster http://schemas.monster.com/Current/XSD/Job.xsd http://schemas.monster.com/Monster/NIS http://schemas.monster.com/Current/Extensions/NIS/XSD/NISJob.xsd">

    <nis:NISJob>
      <Job jobRefCode="13425840" jobAction="addOrUpdate" jobComplete="true">
          <RecruiterReference>
            <UserName>hj45_32179</UserName>
          </RecruiterReference>
          <CompanyReference>
            <CompanyXCode>xhj45_36079x</CompanyXCode>
            <CompanyName>
              <![CDATA[Clarion Hotel]]>
            </CompanyName>
          </CompanyReference>
          <Channel monsterId="1180"/>
            <JobInformation>
                <JobTitle>
                    <![CDATA[Front Desk Agent, Bartender, Houseperson]]>
                </JobTitle>
                <JobType monsterId="1"/>
                <JobStatus monsterId="4"/>
                <DisableApplyOnline>true</DisableApplyOnline>
                <HideCompanyInfo>true</HideCompanyInfo>
            </JobInformation>
        </Job>
        <nis:AdditionalProducts/>
    </nis:NISJob>
</nis:Jobs>

XLT attempt:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nis="http://schemas.monster.com/Monster/NIS" xmlns="http://schemas.monster.com/Monster" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.monster.com/Monster http://schemas.monster.com/Current/XSD/Job.xsd http://schemas.monster.com/Monster/NIS http://schemas.monster.com/Current/Extensions/NIS/XSD/NISJob.xsd"
>

<xsl:template match="/">
  <html>
  <body>
    <h2>Ads in Feed</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>CompanyXCode</th>
      </tr>
      <xsl:for-each select="nis:Jobs/nis:NISJob">
        <tr>
          <td><xsl:value-of select="Job/CompanyReference/CompanyXCode"/></td>
        </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

I have tried this in PHP using the XSLTProcessor, and I've also tried it in W3Schools' Tryit Editor ( http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog_ex2 ) with no luck.

I'm guessing that there's a problem with the uneven namespace usage in the XML. Any hopes of working around that that anyone knows of?

Thanks in advance!

Your code works fine for me (Saxon 6.5.5). However, an html element does not need a namespace and not all values are retrieved from the file. So, you need to rethink your usage of namespaces.

EDIT : A second attempt at writing your stylesheet is below. I have used just two namespaces, all elements in your input XML are either in the http://schemas.monster.com/Monster/NIS or http://schemas.monster.com/Monster namespace.

The very first line of your input XML declares a default namespace , which is

xmlns="http://schemas.monster.com/Monster"

Any elements that are not prefixed explicitly, implicitly belong to this namespace. That is why you have to refer to the Job element as mon:Job , for instance.

Finally, use exclude-result-prefixes to prevent XSLT from outputting unwanted namespaces.

Stylesheet

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nis="http://schemas.monster.com/Monster/NIS"
xmlns:mon="http://schemas.monster.com/Monster"
exclude-result-prefixes="nis mon">

<xsl:output method="html" indent="yes" />

<xsl:template match="/">
  <html>
  <body>
    <h2>Ads in Feed</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>CompanyXCode</th>
      </tr>
      <xsl:for-each select="nis:Jobs/nis:NISJob">
        <tr>
          <td><xsl:value-of select="mon:Job/mon:CompanyReference/mon:CompanyXCode"/></td>
        </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

Output

<html>
   <body>
      <h2>Ads in Feed</h2>
      <table border="1">
         <tr bgcolor="#9acd32">
            <th>CompanyXCode</th>
         </tr>
         <tr>
            <td>xhj45_36079x</td>
         </tr>
      </table>
   </body>
</html>

The namespace definition and usage in your XSLT is wrong.

Them XML file uses two namespaces:

For Xpath you need to define you own prefixes. That can be the same prefix like in the XML document, or a different one.

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:nis="http://schemas.monster.com/Monster/NIS" 
  xmlns:monster="http://schemas.monster.com/Monster"
>

<xsl:template match="/">
  <html>
  <body>
    <h2>Ads in Feed</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>CompanyXCode</th>
      </tr>
      <xsl:for-each select="nis:Jobs/nis:NISJob">
        <tr>
          <td><xsl:value-of select="monster:Job/monster:CompanyReference/monster:CompanyXCode"/></td>
        </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM