Difficulty with data masking xpath element.

We are using an AssignMessage policy to set the request to a SOAP target and want to hide the MerchantKey value (which are in the body)

 

<soap:Envelope 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <SchemaName 
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey> 
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody> 
      </Request> 
    </SchemaName> 
  </soap:Body> 
</soap:Envelope>

 

I have sent in a Data Masking request something like this:

 

<MaskDataConfiguration name="default">
    <Namespaces>
        <Namespace prefix="soap">http://schemas.xmlsoap.org/soap/envelope/</Namespace>
        <Namespace prefix="FindBoardedCard">http://schemas.merchantwarehouse.com/merchantware/v46/</Namespace>
    </Namespaces>
    <XPathsRequest>
        <XPathRequest>/soap:Envelope/soap:Body/FindBoardedCard/Credentials/MerchantKey</XPathRequest>
    </XPathsRequest>
</MaskDataConfiguration>

 

 

I have also tried several other permutations. Ideally, I would like to just mask only the MerchantKey. I have attempted to use some xpath evaluators, but for some of these attempts, even though the xpath evaluator would find the element, when enabling the data masking for the same payload and xpath, it wouldn't mask the element. I wasn't able to find any examples which are quite similar to the structure of this payload. Any assistance would be greatly appreciated.

 

Solved Solved
1 2 444
1 ACCEPTED SOLUTION

I think I can help you. 

XML is complicated, and XML Namespaces make things even more challenging. 

Your inbound message

 

 

<soap:Envelope 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <SchemaName 
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey> 
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody> 
      </Request> 
    </SchemaName> 
  </soap:Body> 
</soap:Envelope>

 

...uses two distinct namespaces: 

The first one uses an explicit namespace prefix: "soap". The way prefixes work: For any element in the document that bears that prefix, the element is said to be defined in the referred namespace (http://www.w3.org...). The prefix itself carries no meaning. It's just a moniker, a reference to an actual namespace. The following document uses ns1 as the prefix, and is informationally equivalent to yours:

 

<ns1:Envelope
    xmlns:ns1="http://www.w3.org/2003/05/soap-envelope">
  <ns1:Body>
    <SchemaName
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey>
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody>
      </Request>
    </SchemaName>
  </ns1:Body>
</ns1:Envelope>

 

(Informationally equivalent means, all compliant XML processors should treat it as EXACTLY the same information. to repeat: the actual prefix does not matter, it's the namespace that's important).

The second namespace in your document does not use an explicit namespace prefix. (This is where it gets a little more complicated). When there's no prefix, then, every unqualified element (no prefix and no xmlns= attribute) beneath that parent element is said to be defined in the given namespace. This namespace is known as "the default namespace" for all descendants.

Because of the use of xmlns= with no prefix, elements like SchemaName, Credentials, MerchantName and so on are all defined in the default namespace , which is "http://schemas.company.com/company/v46/"

Using a default namespace is just an alternative to using a prefix. Your document is informationally equivalent to this:

 

<Envelope 
    xmlns="http://www.w3.org/2003/05/soap-envelope">
  <Body>
    <SchemaName 
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey> 
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody> 
      </Request> 
    </SchemaName> 
  </Body> 
</Envelope>

 

and also this:

 

<soap:Envelope 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <ns1:SchemaName 
        xmlns:ns1="http://schemas.company.com/company/v46/">
      <ns1:Credentials>
        <ns1:MerchantName>Our-Name</ns1:MerchantName>
        <ns1:MerchantKey>{private.key}</ns1:MerchantKey> 
      </ns1:Credentials>
      <ns1:Request>
        <ns1:RequestBody>123456</ns1:RequestBody> 
      </ns1:Request> 
    </ns1:SchemaName> 
  </soap:Body> 
</soap:Envelope>

 

And, for the final twist of complication: there is no analogous "default namespace" mechanism in xpath.  If you want to refer to a namespace-qualified element in an XPath expression, you must declare that namespace and its prefix explicitly.

What you want is something like this:

 

<MaskDataConfiguration name="default">
  <Namespaces>
    <Namespace prefix="s">http://www.w3.org/2003/05/soap-envelope</Namespace>
    <Namespace prefix="ns1">http://schemas.company.com/company/v46/</Namespace>
  </Namespaces>
  <XPathsRequest>
    <XPathRequest>/s:Envelope/s:Body/ns1:SchemaName/ns1:Credentials/ns1:MerchantKey</XPathRequest>
  </XPathsRequest>
</MaskDataConfiguration>

 

Things to notice:

  1. I have explicitly declared two namespaces and their corresponding prefixes
  2. the s: prefix refers to the soap namespace. BTW, your original MaskDataConfig used the wrong actual namespace - check it. It specifies http://schemas.xmlsoap.org/etc, and the document you provided uses http://www.w3.org/etc . They do not match. The former is the soap 1.1 namespace, the latter is used with soap 1.2. (more on that)
  3. Every element in the xpath expression has a namespace prefix
  4. The prefixes i use in the xpath need not match the prefixes used in the original document. It's the namespace itself, not the prefix, that matters.
  5. I use ns1:ELEMENT to refer to the element with local name ELEMENT in the namespace http://schemas.company.com/company/v46/

View solution in original post

2 REPLIES 2

I think I can help you. 

XML is complicated, and XML Namespaces make things even more challenging. 

Your inbound message

 

 

<soap:Envelope 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <SchemaName 
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey> 
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody> 
      </Request> 
    </SchemaName> 
  </soap:Body> 
</soap:Envelope>

 

...uses two distinct namespaces: 

The first one uses an explicit namespace prefix: "soap". The way prefixes work: For any element in the document that bears that prefix, the element is said to be defined in the referred namespace (http://www.w3.org...). The prefix itself carries no meaning. It's just a moniker, a reference to an actual namespace. The following document uses ns1 as the prefix, and is informationally equivalent to yours:

 

<ns1:Envelope
    xmlns:ns1="http://www.w3.org/2003/05/soap-envelope">
  <ns1:Body>
    <SchemaName
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey>
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody>
      </Request>
    </SchemaName>
  </ns1:Body>
</ns1:Envelope>

 

(Informationally equivalent means, all compliant XML processors should treat it as EXACTLY the same information. to repeat: the actual prefix does not matter, it's the namespace that's important).

The second namespace in your document does not use an explicit namespace prefix. (This is where it gets a little more complicated). When there's no prefix, then, every unqualified element (no prefix and no xmlns= attribute) beneath that parent element is said to be defined in the given namespace. This namespace is known as "the default namespace" for all descendants.

Because of the use of xmlns= with no prefix, elements like SchemaName, Credentials, MerchantName and so on are all defined in the default namespace , which is "http://schemas.company.com/company/v46/"

Using a default namespace is just an alternative to using a prefix. Your document is informationally equivalent to this:

 

<Envelope 
    xmlns="http://www.w3.org/2003/05/soap-envelope">
  <Body>
    <SchemaName 
        xmlns="http://schemas.company.com/company/v46/">
      <Credentials>
        <MerchantName>Our-Name</MerchantName>
        <MerchantKey>{private.key}</MerchantKey> 
      </Credentials>
      <Request>
        <RequestBody>123456</RequestBody> 
      </Request> 
    </SchemaName> 
  </Body> 
</Envelope>

 

and also this:

 

<soap:Envelope 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <ns1:SchemaName 
        xmlns:ns1="http://schemas.company.com/company/v46/">
      <ns1:Credentials>
        <ns1:MerchantName>Our-Name</ns1:MerchantName>
        <ns1:MerchantKey>{private.key}</ns1:MerchantKey> 
      </ns1:Credentials>
      <ns1:Request>
        <ns1:RequestBody>123456</ns1:RequestBody> 
      </ns1:Request> 
    </ns1:SchemaName> 
  </soap:Body> 
</soap:Envelope>

 

And, for the final twist of complication: there is no analogous "default namespace" mechanism in xpath.  If you want to refer to a namespace-qualified element in an XPath expression, you must declare that namespace and its prefix explicitly.

What you want is something like this:

 

<MaskDataConfiguration name="default">
  <Namespaces>
    <Namespace prefix="s">http://www.w3.org/2003/05/soap-envelope</Namespace>
    <Namespace prefix="ns1">http://schemas.company.com/company/v46/</Namespace>
  </Namespaces>
  <XPathsRequest>
    <XPathRequest>/s:Envelope/s:Body/ns1:SchemaName/ns1:Credentials/ns1:MerchantKey</XPathRequest>
  </XPathsRequest>
</MaskDataConfiguration>

 

Things to notice:

  1. I have explicitly declared two namespaces and their corresponding prefixes
  2. the s: prefix refers to the soap namespace. BTW, your original MaskDataConfig used the wrong actual namespace - check it. It specifies http://schemas.xmlsoap.org/etc, and the document you provided uses http://www.w3.org/etc . They do not match. The former is the soap 1.1 namespace, the latter is used with soap 1.2. (more on that)
  3. Every element in the xpath expression has a namespace prefix
  4. The prefixes i use in the xpath need not match the prefixes used in the original document. It's the namespace itself, not the prefix, that matters.
  5. I use ns1:ELEMENT to refer to the element with local name ELEMENT in the namespace http://schemas.company.com/company/v46/

@dchiesa1 Works great now. Thanks so much! The non-explicit namespaces--and namespaces in general--tend to throw me.