Home > Software design >  XSL Transform for-each not matching
XSL Transform for-each not matching

Time:01-11

I'm working on an XML transform to migrate incoming XML from an old format to a new format. For some reason, the <xsl:for-each> isn't matching the XML, and I'm unable to figure out why. My assumption is it's related to the namespaces on the records and record elements.

My XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:h="https://github.com/rSmart/ce-tech-docs/tree/master/v2_0"
                exclude-result-prefixes="h">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="/">
    <hrmanifest xmlns="https://github.com/KualiCo/ce-tech-docs/tree/master/v3_0" schemaVersion="3.0">
      <xsl:attribute name="statusEmailRecipient"><xsl:value-of
          select="/*/@statusEmailRecipient"></xsl:value-of></xsl:attribute>
      <xsl:attribute
        name="recordCount"><xsl:value-of select="/*/@recordCount"></xsl:value-of></xsl:attribute>
      <h:records xmlns:h="https://github.com/KualiCo/ce-tech-docs/tree/master/v3_0">
        <xsl:for-each select="hrmanifest/h:records/h:record">
          <record>
            Text
          </record>
        </xsl:for-each>
      </h:records>
    </hrmanifest>
  </xsl:template>
</xsl:stylesheet>

My sample XML, with some values redacted, as it's not even getting to those at this point:

<?xml version='1.0' encoding='UTF-8'?>
<hrmanifest xmlns="https://github.com/rSmart/ce-tech-docs/tree/master/v2_0" schemaVersion="2.0"
  statusEmailRecipient="[REDACTED]" recordCount="20594">
  <h:records xmlns:h="https://github.com/rSmart/ce-tech-docs/tree/master/v2_0">
    <h:record principalId="[REDACTED]" principalName="[REDACTED]" active="true">
      <h:affiliations>
        <h:affiliation affiliationType="[REDACTED]" campus="[REDACTED]" default="true" active="true">
          <h:employment employeeStatus="[REDACTED]" employeeType="[REDACTED]" baseSalaryAmount="[REDACTED]"
            primaryDepartment="[REDACTED]" employeeId="[REDACTED]" />
        </h:affiliation>
      </h:affiliations>
      <h:addresses>
        <h:address addressTypeCode="WRK" addressLine1="[REDACTED]" city="[REDACTED]"
          stateOrProvince="[REDACTED]" postalCode="[REDACTED]" country="[REDACTED]" default="true" active="true" />
      </h:addresses>
      <h:names>
        <h:name nameCode="PRFR" firstName="[REDACTED]" lastName="[REDACTED]" default="true"
          active="true" />
      </h:names>
      <h:phones>
        <h:phone phoneType="WRK" phoneNumber="[REDACTED]" default="true" active="true" />
      </h:phones>
      <h:emails>
        <h:email emailType="WRK" emailAddress="[REDACTED]" default="true"
          active="true" />
      </h:emails>
    </h:record>
    <h:record principalId="[REDACTED]" principalName="[REDACTED]" active="true">
      <h:affiliations>
        <h:affiliation affiliationType="[REDACTED]" campus="[REDACTED]" default="true" active="true">
          <h:employment employeeStatus="[REDACTED]" employeeType="[REDACTED]" baseSalaryAmount="[REDACTED]"
            primaryDepartment="[REDACTED]" employeeId="[REDACTED]" />
        </h:affiliation>
      </h:affiliations>
      <h:addresses>
        <h:address addressTypeCode="WRK" addressLine1="[REDACTED]" city="[REDACTED]"
          stateOrProvince="[REDACTED]" postalCode="[REDACTED]" country="[REDACTED]" default="true" active="true" />
      </h:addresses>
      <h:names>
        <h:name nameCode="PRFR" firstName="[REDACTED]" lastName="[REDACTED]" default="true"
          active="true" />
      </h:names>
      <h:phones>
        <h:phone phoneType="WRK" phoneNumber="[REDACTED]" default="true" active="true" />
      </h:phones>
      <h:emails>
        <h:email emailType="WRK" emailAddress="[REDACTED]" default="true"
          active="true" />
      </h:emails>
    </h:record>
  </h:records>
</hrmanifest>

Thanks!

CodePudding user response:

There are two problems with your stylesheet:

  1. The root element hrmanifest is in the same namespace as its descendants, even though it does not have the same h: prefix;

  2. You are overwriting the namespace declaration in the xsl:stylesheet start-tag with the namespace declaration in the literal element h:records. As a result, the h: prefix is bound to a different namespace and your expressions do not match any elements in the input XML.

A simple solution is to declare a different prefix in the xsl:stylesheet start-tag and use it for the root element hrmanifest too:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:g="https://github.com/rSmart/ce-tech-docs/tree/master/v2_0"
                exclude-result-prefixes="g">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="/">
    <hrmanifest xmlns="https://github.com/KualiCo/ce-tech-docs/tree/master/v3_0" schemaVersion="3.0">
    <!-- omitted -->
      <h:records xmlns:h="https://github.com/KualiCo/ce-tech-docs/tree/master/v3_0">
        <xsl:for-each select="g:hrmanifest/g:records/g:record">
          <record>
            Text
          </record>
        </xsl:for-each>
      </h:records>
    </hrmanifest>
  </xsl:template>
</xsl:stylesheet>
  • Related