> ## Documentation Index
> Fetch the complete documentation index at: https://developers.pcibooking.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Filters

> Define XML, JSON, form-encoded, and query string content filters that tell PCI Booking where card data fields are in your messages

A content filter is an XML configuration within a [target profile](/account-setup/target-profiles) that tells PCI Booking exactly where card data fields are located in a message. Content filters are used for both **tokenization** (extracting card data) and **token replacement** (injecting card data).

## Supported Message Formats

Content filters support four message formats. Set the `type` attribute on the `<transform>` element to match your message format.

| Format                | Type Value    | Selector Syntax | Description                              |
| --------------------- | ------------- | --------------- | ---------------------------------------- |
| **XML body**          | `body`        | XPath           | XML or SOAP message bodies               |
| **JSON body**         | `body`        | JSONPath        | JSON message bodies                      |
| **Form-encoded body** | `body`        | Field name      | `application/x-www-form-urlencoded` data |
| **URL query string**  | `querystring` | Parameter name  | Card data in URL query parameters        |

PCI Booking detects whether body content is XML, JSON, or form-encoded based on the content type header.

## Content Filter Structure

A content filter is an XML document with this general structure:

```xml theme={null}
<ContentDefinition>
  <transform type="body">
    <content selector="XPath or JSONPath to card block">
      <number selector="path/to/card/number" />
      <expYear selector="path/to/exp/year" />
      <expMonth selector="path/to/exp/month" />
      <securityCode selector="path/to/cvv" />
      <nameOnCard selector="path/to/name" />
      <type selector="path/to/card/type" />
    </content>
  </transform>
</ContentDefinition>
```

The `<content>` element's `selector` attribute points to the parent element containing card fields. Each child element then uses a relative selector to locate its specific field within that parent.

## Format Examples

<Tabs>
  <Tab title="XML Body">
    For XML messages, use XPath expressions. Use `local-name()` to match elements regardless of XML namespace prefix.

    **Tokenization filter** (extracting card data):

    ```xml theme={null}
    <ContentDefinition>
      <transform type="body">
        <content selector="//*[local-name()='PaymentCard']">
          <number selector="*[local-name()='CardNumber']" />
          <expYear selector="*[local-name()='ExpireDate']/@Year" format="YYYY" />
          <expMonth selector="*[local-name()='ExpireDate']/@Month" format="MM" />
          <nameOnCard selector="*[local-name()='CardHolderName']" />
          <securityCode selector="*[local-name()='SeriesCode']/@SeriesCode" />
          <type selector="@CardCode" />
        </content>
      </transform>
    </ContentDefinition>
    ```

    **Token replacement filter** (injecting card data):

    ```xml theme={null}
    <ContentDefinition>
      <transform type="body">
        <content selector="//*[local-name()='PaymentCard']">
          <number selector="*[local-name()='CardNumber']" />
          <expYear selector="*[local-name()='ExpireDate']/@Year" format="YYYY" />
          <expMonth selector="*[local-name()='ExpireDate']/@Month" format="MM" />
          <nameOnCard selector="*[local-name()='CardHolderName']" />
          <securityCode selector="*[local-name()='SeriesCode']/@SeriesCode" />
          <type selector="@CardCode">
            <list>
              <item key="VI" value="Visa" />
              <item key="MC" value="MasterCard" />
              <item key="AX" value="AMEX" />
              <item key="DC" value="DinersClub" />
              <item key="JC" value="JCB" />
            </list>
          </type>
        </content>
      </transform>
    </ContentDefinition>
    ```
  </Tab>

  <Tab title="JSON Body">
    For JSON messages, use JSONPath expressions.

    ```xml theme={null}
    <ContentDefinition>
      <transform type="body">
        <content selector="$..BankCard">
          <number selector="CardNo" />
          <expYear selector="ExpirationYear" format="YYYY" />
          <expMonth selector="ExpirationMonth" format="MM" />
          <nameOnCard selector="CardHolder" />
          <securityCode selector="CVV" />
          <type selector="CardType" />
        </content>
      </transform>
    </ContentDefinition>
    ```

    <Info>
      When working with JSON, you can use the `tryJsonNumber` attribute on numeric fields (`number`, `expYear`, `expMonth`, `issueNumber`, `type`) to output values as JSON numbers instead of strings.
    </Info>
  </Tab>

  <Tab title="Form-Encoded">
    For `application/x-www-form-urlencoded` data, selectors are the field names directly.

    ```xml theme={null}
    <ContentDefinition>
      <transform type="body">
        <content>
          <number selector="ccNumber" />
          <expYear selector="ccExpYear" format="YY" />
          <expMonth selector="ccExpMonth" format="M" />
          <nameOnCard selector="ccName" />
          <securityCode selector="ccCVV" />
        </content>
      </transform>
    </ContentDefinition>
    ```
  </Tab>

  <Tab title="Query String">
    For card data passed as URL query parameters, set `type="querystring"`.

    ```xml theme={null}
    <ContentDefinition>
      <transform type="querystring">
        <content>
          <number selector="cc" />
          <expYear selector="exp_year" format="YYYY" />
          <expMonth selector="exp_month" format="MM" />
          <securityCode selector="cvv" />
        </content>
      </transform>
    </ContentDefinition>
    ```
  </Tab>
</Tabs>

## Card Data Fields

Each `<content>` element can map the following card fields:

| Element          | Description                         | Attributes                                                          |
| ---------------- | ----------------------------------- | ------------------------------------------------------------------- |
| `<number>`       | Full card number (PAN)              | `selector`, `substring`, `dataSubstring`                            |
| `<expYear>`      | Expiration year                     | `selector`, `format` (`YYYY` or `YY`), `substring`, `dataSubstring` |
| `<expMonth>`     | Expiration month                    | `selector`, `format` (`MM` or `M`), `substring`, `dataSubstring`    |
| `<securityCode>` | CVV / CVC / CID                     | `selector`, `substring`, `dataSubstring`                            |
| `<nameOnCard>`   | Cardholder name                     | `selector`, `substring`, `dataSubstring`                            |
| `<type>`         | Card brand (Visa, MasterCard, etc.) | `selector`, child `<list>` for mapping                              |
| `<issueNumber>`  | Card issue number                   | `selector`                                                          |

### Format Attributes

The `format` attribute controls how date fields are read and written:

* **`expYear`**: `YYYY` (default, four digits) or `YY` (two digits)
* **`expMonth`**: `MM` (two digits with leading zero) or `M` (default, no leading zero)

### Substring Extraction

When a third party combines multiple values into a single field, use substring extraction to isolate the part you need.

* **`substring`** - extracts a portion of the value when **reading** from the message (tokenization). Format: `"startPosition"` or `"startPosition,length"` (zero-based).
* **`dataSubstring`** - extracts a portion of the replacement data when **writing** to the message (token replacement). Same format as `substring`.

Example: expiration date sent as `0125` (MMYY) in a single field:

```xml theme={null}
<expMonth selector="expDate" substring="0,2" format="MM" />
<expYear selector="expDate" substring="2,2" format="YY" />
```

### Card Type Mapping

When a third party uses different card type codes than PCI Booking, add a `<list>` child element to the `<type>` field to map between them.

```xml theme={null}
<type selector="@CardCode">
  <list>
    <item key="VI" value="Visa" />
    <item key="MC" value="MasterCard" />
    <item key="AX" value="AMEX" />
    <item key="DC" value="DinersClub" />
    <item key="DN" value="Dankort" />
    <item key="JC" value="JCB" />
    <item key="UP" value="UnionPay" />
  </list>
</type>
```

The `key` is the third party's code. The `value` is PCI Booking's card type name (see [Supported Card Types](/reference/card-types) for the full list).

## 3D Secure Fields

Content filters can also map 3DS authentication data alongside card fields. Add these as siblings to the card field elements inside `<content>`:

| Element          | Description                                    |
| ---------------- | ---------------------------------------------- |
| `<auth>`         | Authentication value (CAVV or AAV)             |
| `<eci>`          | Electronic Commerce Indicator                  |
| `<xid>`          | 3DS v1 transaction identifier                  |
| `<acs>`          | ACS Transaction ID (3DS v2)                    |
| `<version>`      | 3DS protocol version                           |
| `<merchantName>` | Merchant name used in the 3DS challenge        |
| `<sli>`          | Security Level Indicator (MasterCard-specific) |

Example with 3DS fields:

```xml theme={null}
<content selector="//*[local-name()='PaymentCard']">
  <number selector="*[local-name()='CardNumber']" />
  <expYear selector="*[local-name()='ExpireDate']/@Year" />
  <expMonth selector="*[local-name()='ExpireDate']/@Month" />
  <auth selector="*[local-name()='ThreeDSecure']/*[local-name()='AuthValue']" />
  <eci selector="*[local-name()='ThreeDSecure']/*[local-name()='ECI']" />
  <xid selector="*[local-name()='ThreeDSecure']/*[local-name()='XID']" />
</content>
```

## Multiple Cards in One Message

If a message contains multiple cards (e.g., a batch of reservations), add a `reservationSelector` attribute to the `<content>` element. This XPath expression identifies each repeating card block, and PCI Booking processes each one independently.

```xml theme={null}
<content selector="//*[local-name()='PaymentCard']"
         reservationSelector="//*[local-name()='Reservation']">
  <number selector="*[local-name()='CardNumber']" />
  <!-- other fields -->
</content>
```

PCI Booking iterates over every element matching `reservationSelector` and applies the card field selectors within each.

## Next Steps

<CardGroup cols={2}>
  <Card title="Target Profiles" icon="book" href="/account-setup/target-profiles">
    Create and manage profiles that use content filters
  </Card>

  <Card title="Supported Card Types" icon="code" href="/reference/card-types">
    Full list of card type values for card type mapping
  </Card>

  <Card title="Tokenization on Response" icon="book" href="/capture-cards/tokenization-on-response">
    Tokenize card data from third-party responses
  </Card>

  <Card title="Token Replacement in Request" icon="book" href="/use-tokens/token-replacement-in-request">
    Replace tokens with real card data in outbound requests
  </Card>
</CardGroup>
