Hi!
I am currently working with Filter2 transforms and XPath transforms. And I have
problems when namespace prefixes are used in some element that is present in a
filter2-xpath value.
I provide the code that I am using to calculate transformation output at the end
of the mail.
Example: suppose the following xml document:
<Document>
<bla:ToBeSigned xmlns:bla="http://www.bla.com">
<!-- comment -->
<bla:Data/>
<bla:NotToBeSigned>
<bla:ReallyToBeSigned>
<!-- comment -->
<bla:Data/>
</bla:ReallyToBeSigned>
</bla:NotToBeSigned>
</bla:ToBeSigned>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" >
<ds:SignedInfo>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.
org/2002/06/xmldsig-filter2">
<ds:XPath Filter="intersect">
//ToBeSigned </ds:XPath>
<ds:XPath Filter="subtract">
//NotToBeSigned </ds:XPath>
<ds:XPath Filter="union">
//ReallyToBeSigned </ds:XPath>
</ds:Transform>
</ds:Transforms>
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
</Document>
Questions: [ see the code below ... ]
1) a 'intersect' filter2 with value '//bla:ToBeSigned' is not working. I get an
exception telling me that the Prefix (bla) must resolve to a namespace. Actually
everything that is prefixed with something different than 'ds' will give me that
exception.
But if I activate the commented lines in the code below, it will work.
I wouldn't like to need to add a call to 'setXPathNamespaceContext' every time a
prefix (with corresponding ns) shows upp. Actually, it would be almost
impossible to do this dynamically as an element using a prefix does not need to
have an xmlns:that_prefix as attribute.
What am i doing wrong? Solutions?
2) a 'intersect' filter2 with value '//ds:Signature' will work. Why? Is it so
that by default a ns context node is always added for the prefix 'ds' with the
value 'http://www.w3.org/2000/09/xmldsig#' ?
Thanks!
-R
public class AnotherSignTextCreator
{
/**
* Create the data to sign from a Document given a series of
* transformations.
*
* Example of 'filters' parameter:
* [0][0] = "intersect"
* [0][1] = "//bla:ToBeSigned"
* [1][0] = "subtract"
* [1][1] = "//ds:Signature"
*
* @param document A Document containing the xml input data
* @param transforms A String array with the transforms to apply to the
document.
* @exception Exception If an error occurs
*/
public byte[] getSignText( final Document document,
final String[][] filters )
throws Exception
{
if( !Init.isInitialized() )
{
Init.init();
}
Transforms transforms = new Transforms( document );
transforms.addTransform( Transforms.TRANSFORM_XPATH2FILTER,
newInstances( document, filters ) );
XMLSignatureInput signatureInput = new XMLSignatureInput((Node) document );
XMLSignatureInput result = transforms.performTransforms( signatureInput );
byte res[] = result.getBytes();
return res;
}
/**
* Creates a NodeList for a Transforms
*/
public static NodeList newInstances( Document doc, String[][] filters )
throws XMLSecurityException
{
HelperNodeList nl = new HelperNodeList();
nl.appendChild( doc.createTextNode("\n") );
for ( int i = 0; i < filters.length; i++ )
{
String type = filters[i][0];
String xpath = filters[i][1];
if( type.equals( XPath2FilterContainer.INTERSECT ) )
{
XPath2FilterContainer c = XPath2FilterContainer.
newInstanceIntersect( doc, xpath );
//c.setXPathNamespaceContext( "bla", "http://www.bla.com" );
nl.appendChild( c.getElement() );
nl.appendChild( doc.createTextNode("\n") );
}
if( type.equals( XPath2FilterContainer.SUBTRACT ) )
{
XPath2FilterContainer c = XPath2FilterContainer.
newInstanceSubtract( doc, xpath );
//c.setXPathNamespaceContext( "bla", "http://www.bla.com" );
nl.appendChild( c.getElement() );
nl.appendChild( doc.createTextNode("\n") );
}
if( type.equals( XPath2FilterContainer.UNION ) )
{
XPath2FilterContainer c = XPath2FilterContainer.
newInstanceUnion( doc, xpath );
//c.setXPathNamespaceContext( "bla", "http://www.bla.com" );
nl.appendChild( c.getElement() );
nl.appendChild( doc.createTextNode("\n") );
}
}
return nl;
}
}