Export (0) Print
Expand All

XmlDsigXsltTransform Class

Represents the XSLT transform for a digital signature as defined by the W3C.

System::Object
  System.Security.Cryptography.Xml::Transform
    System.Security.Cryptography.Xml::XmlDsigXsltTransform

Namespace:  System.Security.Cryptography.Xml
Assembly:  System.Security (in System.Security.dll)

[HostProtectionAttribute(SecurityAction::LinkDemand, MayLeakOnAbort = true)]
public ref class XmlDsigXsltTransform : public Transform

The XmlDsigXsltTransform type exposes the following members.

  NameDescription
Public methodXmlDsigXsltTransform()Initializes a new instance of the XmlDsigXsltTransform class.
Public methodXmlDsigXsltTransform(Boolean)Initializes a new instance of the XmlDsigXsltTransform class with comments, if specified.
Top

  NameDescription
Public propertyAlgorithmGets or sets the Uniform Resource Identifier (URI) that identifies the algorithm performed by the current transform. (Inherited from Transform.)
Public propertyContextGets or sets an XmlElement object that represents the document context under which the current Transform object is running. (Inherited from Transform.)
Public propertyInputTypesGets an array of types that are valid inputs to the LoadInput method of the current XmlDsigXsltTransform object. (Overrides Transform::InputTypes.)
Public propertyOutputTypesGets an array of types that are possible outputs from the GetOutput methods of the current XmlDsigXsltTransform object. (Overrides Transform::OutputTypes.)
Public propertyPropagatedNamespacesGets or sets a Hashtable object that contains the namespaces that are propagated into the signature. (Inherited from Transform.)
Public propertyResolverSets the current XmlResolver object. (Inherited from Transform.)
Top

  NameDescription
Public methodEquals(Object)Determines whether the specified object is equal to the current object. (Inherited from Object.)
Protected methodFinalizeAllows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.)
Public methodGetDigestedOutputWhen overridden in a derived class, returns the digest associated with a Transform object. (Inherited from Transform.)
Public methodGetHashCodeServes as the default hash function. (Inherited from Object.)
Protected methodGetInnerXmlReturns an XML representation of the parameters of the XmlDsigXsltTransform object that are suitable to be included as subelements of an XMLDSIG <Transform> element. (Overrides Transform::GetInnerXml().)
Public methodGetOutput()Returns the output of the current XmlDsigXsltTransform object. (Overrides Transform::GetOutput().)
Public methodGetOutput(Type)Returns the output of the current XmlDsigXsltTransform object of type Stream. (Overrides Transform::GetOutput(Type).)
Public methodGetTypeGets the Type of the current instance. (Inherited from Object.)
Public methodGetXmlReturns the XML representation of the current Transform object. (Inherited from Transform.)
Public methodLoadInnerXmlParses the specified XmlNodeList object as transform-specific content of a <Transform> element and configures the internal state of the current XmlDsigXsltTransform object to match the <Transform> element. (Overrides Transform::LoadInnerXml(XmlNodeList).)
Public methodLoadInputLoads the specified input into the current XmlDsigXsltTransform object. (Overrides Transform::LoadInput(Object).)
Protected methodMemberwiseCloneCreates a shallow copy of the current Object. (Inherited from Object.)
Public methodToStringReturns a string that represents the current object. (Inherited from Object.)
Top

The XmlDsigXPathTransform class allows you to address an XML document using an XSLT transformation. This class uses XSLT to transform XML nodes into other XML nodes that you want to sign or encrypt.

Use the XmlDsigXsltTransform class to sign or encrypt specific parts of an XML document using an XSLT transformation.

The Uniform Resource Identifier (URI) that describes the XmlDsigXsltTransform class is defined by the XmlDsigXsltTransformUrl field.

For more information about the XSLT transform, see Section 6.6.5 of the XMLDSIG specification, which is available from the W3C at www.w3.org/TR/xmldsig-core/.

NoteNote

The HostProtectionAttribute attribute applied to this type or member has the following Resources property value: MayLeakOnAbort. The HostProtectionAttribute does not affect desktop applications (which are typically started by double-clicking an icon, typing a command, or entering a URL in a browser). For more information, see the HostProtectionAttribute class or SQL Server Programming and Host Protection Attributes.

This section contains two code examples. The first code example shows how to sign and verify an XML document using the XmlDsigXsltTransform class with an envelope signature. The second code example demonstrates how to use members of the XmlDsigXsltTransform class.

Example #1

// 
// This example signs an XML file using an 
// envelope signature. It then verifies the  
// signed XML. 
//
#using <System.Xml.dll>
#using <System.Security.dll>
#using <System.dll>

using namespace System;
using namespace System::Security::Cryptography;
using namespace System::Security::Cryptography::X509Certificates;
using namespace System::Security::Cryptography::Xml;
using namespace System::Text;
using namespace System::Xml;

// Create the XML that represents the transform. 
static XmlDsigXsltTransform^ CreateXsltTransform( String^ xsl )
{
   XmlDocument^ doc = gcnew XmlDocument;
   doc->LoadXml( xsl );
   XmlDsigXsltTransform^ xform = gcnew XmlDsigXsltTransform;
   xform->LoadInnerXml( doc->ChildNodes );
   return xform;
}


// Sign an XML file and save the signature in a new file. 
static void SignXmlFile( String^ FileName, String^ SignedFileName, RSA^ Key, String^ XSLString )
{

   // Create a new XML document.
   XmlDocument^ doc = gcnew XmlDocument;

   // Format the document to ignore white spaces.
   doc->PreserveWhitespace = false;

   // Load the passed XML file using it's name.
   doc->Load( gcnew XmlTextReader( FileName ) );

   // Create a SignedXml object.
   SignedXml^ signedXml = gcnew SignedXml( doc );

   // Add the key to the SignedXml document. 
   signedXml->SigningKey = Key;

   // Create a reference to be signed.
   Reference^ reference = gcnew Reference;
   reference->Uri = L"";

   // Add an enveloped transformation to the reference.
   XmlDsigEnvelopedSignatureTransform^ env = gcnew XmlDsigEnvelopedSignatureTransform;
   reference->AddTransform( env );

   // Create an XmlDsigXPathTransform object using  
   // the helper method 'CreateXPathTransform' defined 
   // later in this sample.
   XmlDsigXsltTransform^ XsltTransform = CreateXsltTransform( XSLString );

   // Add the transform to the reference.
   reference->AddTransform( XsltTransform );

   // Add the reference to the SignedXml object.
   signedXml->AddReference( reference );

   // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
   KeyInfo^ keyInfo = gcnew KeyInfo;
   keyInfo->AddClause( gcnew RSAKeyValue( dynamic_cast<RSA^>(Key) ) );
   signedXml->KeyInfo = keyInfo;

   // Compute the signature.
   signedXml->ComputeSignature();

   // Get the XML representation of the signature and save 
   // it to an XmlElement object.
   XmlElement^ xmlDigitalSignature = signedXml->GetXml();

   // Append the element to the XML document.
   doc->DocumentElement->AppendChild( doc->ImportNode( xmlDigitalSignature, true ) );

   // Save the signed XML document to a file specified 
   // using the passed string.
   XmlTextWriter^ xmltw = gcnew XmlTextWriter( SignedFileName,gcnew UTF8Encoding( false ) );
   doc->WriteTo( xmltw );
   xmltw->Close();
}


// Verify the signature of an XML file and return the result. 
static Boolean VerifyXmlFile( String^ Name )
{

   // Create a new XML document.
   XmlDocument^ xmlDocument = gcnew XmlDocument;

   // Format using white spaces.
   xmlDocument->PreserveWhitespace = true;

   // Load the passed XML file into the document. 
   xmlDocument->Load( Name );

   // Create a new SignedXml object and pass it 
   // the XML document class.
   SignedXml^ signedXml = gcnew SignedXml( xmlDocument );

   // Find the "Signature" node and create a new 
   // XmlNodeList object.
   XmlNodeList^ nodeList = xmlDocument->GetElementsByTagName( L"Signature" );

   // Load the signature node.
   signedXml->LoadXml( dynamic_cast<XmlElement^>(nodeList->Item( 0 )) );

   // Check the signature and return the result. 
   return signedXml->CheckSignature();
}


// Create example data to sign. 
static void CreateSomeXml( String^ FileName )
{

   // Create a new XmlDocument object.
   XmlDocument^ document = gcnew XmlDocument;

   // Create a new XmlNode object.
   XmlNode^ node = document->CreateNode( XmlNodeType::Element, L"", L"MyXML", L"Don't_Sign" );

   // Append the node to the document.
   document->AppendChild( node );

   // Create a new XmlNode object.
   XmlNode^ subnode = document->CreateNode( XmlNodeType::Element, L"", L"ElementToTransform", L"Sign" );

   // Add some text to the node.
   subnode->InnerText = L"Here is some data to sign.";

   // Append the node to the document.
   document->DocumentElement->AppendChild( subnode );

   // Save the XML document to the file name specified.
   XmlTextWriter^ xmltw = gcnew XmlTextWriter( FileName,gcnew UTF8Encoding( false ) );
   document->WriteTo( xmltw );
   xmltw->Close();
}

int main()
{

   // Generate a signing key.
   RSACryptoServiceProvider^ Key = gcnew RSACryptoServiceProvider;
   String^ xsl = L"\r\n    <xs:transform xmlns:xs='http://www.w3.org/1999/XSL/Transform' version='1.0'>\r\n        <xs:template match='/'>\r\n            <xs:apply-templates/>\r\n        </xs:template>\r\n        <xs:template match='ElementToTransform'> \r\n            <transformedElement/>\r\n        </xs:template>\r\n    </xs:transform>";
   try
   {

      // Create an XML file to sign.
      CreateSomeXml( L"Example.xml" );
      Console::WriteLine( L"New XML file created." );

      // Sign the XML that was just created and save it in a  
      // new file.
      SignXmlFile( L"Example.xml", L"SignedExample.xml", Key, xsl );
      Console::WriteLine( L"XML file signed." );

      // Verify the signature of the signed XML.
      Console::WriteLine( L"Verifying signature..." );
      bool result = VerifyXmlFile( L"SignedExample.xml" );

      // Display the results of the signature verification to \ 
      // the console. 
      if ( result )
      {
         Console::WriteLine( L"The XML signature is valid." );
      }
      else
      {
         Console::WriteLine( L"The XML signature is not valid." );
      }
   }
   catch ( CryptographicException^ e ) 
   {
      Console::WriteLine( e->Message );
   }
   finally
   {
      Key->Clear();
   }

   return 1;
}

Example #2

#using <System.Security.dll>
#using <System.dll>
#using <System.Xml.dll>
using namespace System;
using namespace System::IO;
using namespace System::Xml;
using namespace System::Security::Cryptography;
using namespace System::Security::Cryptography::Xml;
using namespace System::Text;

ref class Class1
{
public:
   [STAThread]
   static void Main()
   {
      XmlDocument^ productsXml = LoadProducts();
      XmlNodeList^ xsltNodeList = GetXsltAsNodeList();
      TransformDoc( productsXml, xsltNodeList );

      // Use XmlDsigXsltTransform to resolve a Uri.
      Uri^ baseUri = gcnew Uri( L"http://www.contoso.com" );
      String^ relativeUri = L"xml";
      Uri^ absoluteUri = ResolveUris( baseUri, relativeUri );
      Console::WriteLine( L"This sample completed successfully; "
      L"press Enter to exit." );
      Console::ReadLine();
   }

private:
   static void TransformDoc( XmlDocument^ xmlDoc, XmlNodeList^ xsltNodeList )
   {
      try
      {
         // Construct a new XmlDsigXsltTransform.
         XmlDsigXsltTransform^ xmlTransform = gcnew XmlDsigXsltTransform;

         // Load the Xslt tranform as a node list.
         xmlTransform->LoadInnerXml( xsltNodeList );

         // Load the Xml document to perform the tranform on.
         XmlNamespaceManager^ namespaceManager;
         namespaceManager = gcnew XmlNamespaceManager( xmlDoc->NameTable );
         XmlNodeList^ productsNodeList;
         productsNodeList = xmlDoc->SelectNodes( L"//.", namespaceManager );
         xmlTransform->LoadInput( productsNodeList );

         // Retrieve the output from the transform.
         Stream^ outputStream = (Stream^)xmlTransform->GetOutput(
            System::IO::Stream::typeid );

         // Read the output stream into a stream reader.
         StreamReader^ streamReader = gcnew StreamReader( outputStream );

         // Read the stream into a string.
         String^ outputMessage = streamReader->ReadToEnd();

         // Close the streams.
         outputStream->Close();
         streamReader->Close();

         // Display to the console the Xml before and after 
         // encryption.
         Console::WriteLine( L"\nResult of transformation: {0}", outputMessage );
         ShowTransformProperties( xmlTransform );
      }
      catch ( Exception^ ex ) 
      {
         Console::WriteLine( L"Caught exception in TransformDoc method: {0}", ex );
      }
   }

   static XmlNodeList^ GetXsltAsNodeList()
   {
      String^ transformXml = L"<xsl:transform version='1.0' ";
      transformXml = String::Concat( transformXml,
         L"xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:template match='products'>" );
      transformXml = String::Concat( transformXml,
         L"<table><tr><td>ProductId</td><td>Name</td></tr>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:apply-templates/></table></xsl:template>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:template match='product'><tr>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:apply-templates/></tr></xsl:template>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:template match='productid'><td>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:apply-templates/></td></xsl:template>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:template match='description'><td>" );
      transformXml = String::Concat( transformXml,
         L"<xsl:apply-templates/></td></xsl:template>" );
      transformXml = String::Concat( transformXml,
         L"</xsl:transform>" );
      Console::WriteLine( L"\nCreated the following Xslt tranform:" );
      Console::WriteLine( transformXml );
      XmlDocument^ xmlDoc = gcnew XmlDocument;
      xmlDoc->LoadXml( transformXml );
      return xmlDoc->GetElementsByTagName( L"xsl:transform" );
   }

   // Encrypt the text in the specified XmlDocument. 
   static void ShowTransformProperties( XmlDsigXsltTransform^ xmlTransform )
   {
      String^ classDescription = xmlTransform->ToString();
      Console::WriteLine( L"\n** Summary for {0} **", classDescription );

      // Retrieve the XML representation of the current transform.
      XmlElement^ xmlInTransform = xmlTransform->GetXml();
      Console::WriteLine( L"Xml representation of the current transform:\n{0}",
         xmlInTransform->OuterXml );

      // Ensure the transform is using the proper algorithm.
      xmlTransform->Algorithm = SignedXml::XmlDsigXsltTransformUrl;
      Console::WriteLine( L"Algorithm used: {0}", classDescription );

      // Retrieve the valid input types for the current transform. 
      array<Type^>^validInTypes = xmlTransform->InputTypes;
      Console::WriteLine( L"Transform accepts the following inputs:" );
      for ( int i = 0; i < validInTypes->Length; i++ )
      {
         Console::WriteLine( L"\t{0}", validInTypes[ i ] );

      }

      array<Type^>^validOutTypes = xmlTransform->OutputTypes;
      Console::WriteLine( L"Transform outputs in the following types:" );
      for ( int i = validOutTypes->Length - 1; i >= 0; i-- )
      {
         Console::WriteLine( L"\t {0}", validOutTypes[ i ] );
         if ( validOutTypes[ i ] == Object::typeid )
         {
            Object^ outputObject = xmlTransform->GetOutput();
         }
      }
   }

   // Create an XML document describing various products. 
   static XmlDocument^ LoadProducts()
   {
      String^ contosoProducts = L"<?xml version='1.0'?>";
      contosoProducts = String::Concat( contosoProducts,
         L"<products>" );
      contosoProducts = String::Concat( contosoProducts,
         L"<product><productid>1</productid>" );
      contosoProducts = String::Concat( contosoProducts,
         L"<description>Widgets</description></product>" );
      contosoProducts = String::Concat( contosoProducts,
         L"<product><productid>2</productid>" );
      contosoProducts = String::Concat( contosoProducts,
         L"<description>Gadgits</description></product>" );
      contosoProducts = String::Concat( contosoProducts,
         L"</products>" );
      Console::WriteLine(
         L"\nCreated the following Xml document for tranformation:" );
      Console::WriteLine( contosoProducts );
      XmlDocument^ xmlDoc = gcnew XmlDocument;
      xmlDoc->LoadXml( contosoProducts );
      return xmlDoc;
   }

   // Resolve the specified base and relative Uri's . 
   static Uri^ ResolveUris( Uri^ baseUri, String^ relativeUri )
   {
      XmlUrlResolver^ xmlResolver = gcnew XmlUrlResolver;
      xmlResolver->Credentials =
         System::Net::CredentialCache::DefaultCredentials;

      XmlDsigXsltTransform^ xmlTransform = gcnew XmlDsigXsltTransform;
      xmlTransform->Resolver = xmlResolver;

      Uri^ absoluteUri = xmlResolver->ResolveUri( baseUri, relativeUri );
      if ( absoluteUri != nullptr )
      {
         Console::WriteLine(
         L"\nResolved the base Uri and relative Uri to the following:" );
         Console::WriteLine( absoluteUri );
      }
      else
      {
         Console::WriteLine( L"Unable to resolve the base Uri and relative Uri" );
      }

      return absoluteUri;
   }
};

int main()
{
   Class1::Main();
}

// 
// This sample produces the following output: 
// 
// Created the following Xml document for tranformation: 
// <?xml version='1.0'?><products><product><productid>1</productid><descriptio 
// n>Widgets</description></product><product><productid>2</productid><descript 
// ion>Gadgits</description></product></products> 
// 
// Created the following Xslt tranform: 
// <xsl:transform version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transfor 
// m'><xsl:template match='products'><table><tr><td>ProductId</td><td>Name</td 
// ></tr><xsl:apply-templates/></table></xsl:template><xsl:template match='pro 
// duct'><tr><xsl:apply-templates/></tr></xsl:template><xsl:emplate match='pro 
// ductid'><td><xsl:apply-templates/></td></xsl:template><xsl:template match=' 
// description'><td><xsl:apply-templates/></td></xsl:template></xsl:transform> 
// 
// Result of transformation: <table><tr><td>ProductId</td><td>Name</td></tr><t 
// r><td>1</td><td>Widgets</td></tr><tr><td>2</td><td>Gadgits</td></tr></table 
// > 
// 
// ** Summary for System.Security.Cryptography.Xml.XmlDsigXsltTransform ** 
// Xml representation of the current transform: 
// <Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116" xmlns="h
// ttp://www.w3.org/2000/09/xmldsig#"><xsl:transform version="1.0" xmlns:xsl=" 
// http://www.w3.org/1999/XSL/Transform"><xsl:template match="products"><table
//  xmlns=""><tr><td>ProductId</td><td>Name</td></tr><xsl:apply-templates /></
// table></xsl:template><xsl:template match="product"><tr xmlns=""><xsl:apply-
// templates /></tr></xsl:template><xsl:template match="productid"><td xmlns="
// "><xsl:apply-templates /></td></xsl:template><xsl:template match="descripti
// on"><td xmlns=""><xsl:apply-templates /></td></xsl:template></xsl:transform
// ></Transform> 
// Algorithm used: System.Security.Cryptography.Xml.XmlDsigXsltTransform 
// Transform accepts the following inputs: 
// System.IO.Stream 
// System.Xml.XmlDocument 
// System.Xml.XmlNodeList 
// Transform outputs in the following types: 
// System.IO.Stream 
// 
// Resolved the base Uri and relative Uri to the following: 
// http://www.contoso.com/xml 
// This sample completed successfully; press Enter to exit.

.NET Framework

Supported in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Show:
© 2014 Microsoft