0

I am trying to use XSLT to transform an XML document into a very similar XML document, but with a couple of additions. I'm having trouble getting xsl:copy-of to work properly. When I try to transform the following sample XML document:

<?xml version="1.0" encoding="UTF-8"?>
<mods xmlns="http://www.loc.gov/mods/v3" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink" 
xmlns:mods="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">
  <titleInfo>
    <title>Test title
    </title>
  </titleInfo>
  <subject authority="naf">
    <geographic>Geo subject</geographic>
  </subject>
  <location>
    <physicalLocation>Location here</physicalLocation>
  </location>
  <originInfo>
    <dateCreated keyDate="yes">1904-01-05</dateCreated><dateCreated/>
  </originInfo>
  <typeOfResource>text</typeOfResource>
  <genre authority="aat" valueURI="300026880">correspondence</genre>
  <physicalDescription>
     <extent>3 pages.</extent>
     <note type="physical description">All pages ripped down the 
     middle. 
     </note>
  </physicalDescription>
  <relatedItem type="host" displayLabel="Collection" 
    <titleInfo>
      <title>Collection name</title>
    </titleInfo>
  </relatedItem>
  <accessCondition type="use and reproduction" displayLabel="Use and 
  Reproduction">Access condition here</accessCondition>
  <identifier type="local">IDID</identifier>
</mods>

Using the following XSLT, only the literal values in the XSLT (originInfo, accessCondition) are output in the result XML document. I can't figure out why this is. When I remove all the header info from the source XML, the transform DOES work. But all my XML files have that header, and I want to make the XSLT work with it in - my guess is that my namespace declarations are contradicting each other, but I can't figure out why.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xlink="https://www.w3.org/1999/xlink" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:mods="http://www.loc.gov/mods/v3" version="2.0" exclude- 
result-prefixes="mods">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <mods>
        <xsl:copy-of select="mods/titleInfo"/>
        <xsl:copy-of select="mods/typeOfResource"/>
        <xsl:copy-of select="mods/location"/>
        <xsl:copy-of select="mods/physicalDescription"/>
        <xsl:copy-of select="mods/subject"/>
        <xsl:copy-of select="mods/name"/>
        <xsl:copy-of select="mods/identifier"/>
        <xsl:copy-of select="mods/genre"/>
        <xsl:copy-of select="mods/relatedItem"/>
        <xsl:copy-of select="mods/accessCondition"/>
        <xsl:copy-of select="mods/language"/>
        <xsl:copy-of select="mods/abstract"/>
        <xsl:copy-of select="mods/note"/>
        <originInfo>
            <dateCreated>
              <xsl:value-of select="mods/originInfo/dateCreated"/> 
            </dateCreated>
            <dateCreated encoding="w3cdtf" keyDate="yes" 
            point="start">
              <xsl:value-of select="mods/originInfo/dateCreated"/>
            </dateCreated> 
        </originInfo>
        <accessCondition type="use and reproduction">
            <xsl:text>Copyright statement here</xsl:text>
        </accessCondition>
    </mods>         

</xsl:template>

My expected output is:

 <?xml version="1.0" encoding="UTF-8"?>
    <mods xmlns="http://www.loc.gov/mods/v3" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns:mods="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">
      <titleInfo>
        <title>Test title
        </title>
      </titleInfo>
      <subject authority="naf">
        <geographic>Geo subject</geographic>
      </subject>
      <location>
        <physicalLocation>Location here</physicalLocation>
      </location>
      <typeOfResource>text</typeOfResource>
      <genre authority="aat" valueURI="300026880">correspondence</genre>
      <physicalDescription>
         <extent>3 pages.</extent>
         <note type="physical description">All pages ripped down the 
         middle. 
         </note>
      </physicalDescription>
      <relatedItem type="host" displayLabel="Collection" 
        <titleInfo>
          <title>Collection name</title>
        </titleInfo>
      </relatedItem>
      <accessCondition type="use and reproduction" displayLabel="Use and 
      Reproduction">Access condition here</accessCondition>
      <identifier type="local">IDID</identifier>
<originInfo>
      <dateCreated>1904-01-05 </dateCreated>
      <dateCreated encoding="w3cdtf" keyDate="yes" point="start">1904-01-05 </dateCreated>
   </originInfo>
   <accessCondition type="use and reproduction">Copyright statement here</accessCondition>
</mods>
3
  • Only a guess here but my guess would be that it has somthing to do with the fact that xmlns:mods and your default xmlns on the original XML have the same URI. Looks like it is dropping the default and just keeping the xmlns:mods.... Commented Dec 28, 2018 at 2:24
  • Please post a complete example of the XML input, as well as the expected output. -- Note that (1) <xsl:copy-of select="titleInfo"/> does not do anything, because titleInfo is in a namespace and (2) copying an element copies its namespace too (which is why we need to see your expected output). Commented Dec 28, 2018 at 3:17
  • Thanks; added complete XML and expected output to the original question. The xsl:copy-of select="titleInfo" was a mistake; I corrected in the original. Commented Dec 28, 2018 at 3:35

1 Answer 1

1

There are two problems with your XSLT:

  1. It does not select anything in the XML input, because your XML input puts its nodes in a namespace. If you're using XSLT 2.0, you can solve this by including xpath-default-namespace="http://www.loc.gov/mods/v3" in your xsl:stylesheet opening tag.

  2. It does not put the literal result elements in the target namespace. In order to do this, you must declare the target namespace as the default namespace in one of the higher-level nodes, e.g. by including xmlns="http://www.loc.gov/mods/v3" in your xsl:stylesheet opening tag.

In addition, in order to prevent the original namespace declarations being replicated to every element copied by your stylesheet, you would do well to replace the literal result element <mods> by a copy of the original one.

Here's a complete stylesheet incorporating these changes:

XSLT 2.0

<xsl:stylesheet  version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns="http://www.loc.gov/mods/v3"
xpath-default-namespace="http://www.loc.gov/mods/v3">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/mods">
    <xsl:copy>
        <xsl:copy-of select="titleInfo"/>
        <xsl:copy-of select="typeOfResource"/>
        <xsl:copy-of select="location"/>
        <xsl:copy-of select="physicalDescription"/>
        <xsl:copy-of select="subject"/>
        <xsl:copy-of select="name"/>
        <xsl:copy-of select="identifier"/>
        <xsl:copy-of select="genre"/>
        <xsl:copy-of select="relatedItem"/>
        <xsl:copy-of select="accessCondition"/>
        <xsl:copy-of select="language"/>
        <xsl:copy-of select="abstract"/>
        <xsl:copy-of select="note"/>
        <originInfo>
            <dateCreated>
              <xsl:value-of select="originInfo/dateCreated"/> 
            </dateCreated>
            <dateCreated encoding="w3cdtf" keyDate="yes" point="start">
              <xsl:value-of select="originInfo/dateCreated"/>
            </dateCreated> 
        </originInfo>
        <accessCondition type="use and reproduction">
            <xsl:text>Copyright statement here</xsl:text>
        </accessCondition>
    </xsl:copy>        
</xsl:template>

</xsl:stylesheet>

Demo: http://xsltransform.hikmatu.com/gWmuiHV

Sign up to request clarification or add additional context in comments.

1 Comment

This works perfectly. Thank you so much for such a thorough answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.