Skip to content

GraphQL for XML Users

If you're coming from an XML/SOAP background, this guide will help you understand GraphQL by comparing it to familiar XML concepts and showing how to apply your existing knowledge to modern API development.

Conceptual Mapping: XML to GraphQL

XML Schema vs GraphQL Schema

XML Schema (XSD):

xml
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="PrintJob">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="id" type="xs:string"/>
        <xs:element name="title" type="xs:string"/>
        <xs:element name="status" type="JobStatus"/>
        <xs:element name="customer" type="Customer"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="JobStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="PENDING"/>
      <xs:enumeration value="PRINTING"/>
      <xs:enumeration value="COMPLETED"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

GraphQL Schema:

graphql
type PrintJob {
  id: ID!
  title: String!
  status: JobStatus!
  customer: Customer!
}

enum JobStatus {
  PENDING
  PRINTING
  COMPLETED
}

type Customer {
  id: ID!
  name: String!
  email: String!
}

Key Differences:

  • Simpler Syntax: GraphQL schema is more readable and concise
  • Built-in Types: No need to import namespaces for basic types
  • Relationships: Direct type references instead of complex XML structures
  • Self-Documenting: Comments and descriptions are part of the schema

Data Structure Comparison

XML Document:

xml
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getPrintJobResponse xmlns="http://CoCore.com/api">
      <printJob>
        <id>123</id>
        <title>Business Cards</title>
        <status>PRINTING</status>
        <customer>
          <id>456</id>
          <name>John Doe</name>
          <email>john@example.com</email>
          <orders>
            <order>
              <id>789</id>
              <total>150.00</total>
            </order>
          </orders>
        </customer>
        <files>
          <file>
            <filename>cards.pdf</filename>
            <size>2048576</size>
          </file>
        </files>
      </printJob>
    </getPrintJobResponse>
  </soap:Body>
</soap:Envelope>

GraphQL Response (JSON):

json
{
  "data": {
    "getPrintJob": {
      "id": "123",
      "title": "Business Cards",
      "status": "PRINTING",
      "customer": {
        "id": "456",
        "name": "John Doe",
        "email": "john@example.com",
        "orders": [
          {
            "id": "789",
            "total": 150.00
          }
        ]
      },
      "files": [
        {
          "filename": "cards.pdf",
          "size": 2048576
        }
      ]
    }
  }
}

SOAP Operations vs GraphQL Operations

SOAP Web Service

xml
<!-- WSDL Definition -->
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:message name="GetPrintJobRequest">
    <wsdl:part name="jobId" type="xsd:string"/>
  </wsdl:message>

  <wsdl:message name="GetPrintJobResponse">
    <wsdl:part name="printJob" element="tns:PrintJob"/>
  </wsdl:message>

  <wsdl:portType name="PrintJobService">
    <wsdl:operation name="GetPrintJob">
      <wsdl:input message="tns:GetPrintJobRequest"/>
      <wsdl:output message="tns:GetPrintJobResponse"/>
    </wsdl:operation>
  </wsdl:portType>
</wsdl:definitions>
xml
<!-- SOAP Request -->
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getPrintJob xmlns="http://CoCore.com/api">
      <jobId>123</jobId>
    </getPrintJob>
  </soap:Body>
</soap:Envelope>

GraphQL Equivalent

graphql
# Schema Definition (replaces WSDL)
type Query {
  getPrintJob(id: ID!): PrintJob
}

# Query (replaces SOAP request)
query GetPrintJob {
  getPrintJob(id: "123") {
    id
    title
    status
    customer {
      name
      email
    }
  }
}

Key Advantages of GraphQL over XML/SOAP

1. Reduced Verbosity

XML/SOAP: Lots of boilerplate and envelope structure

xml
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <authentication xmlns="http://CoCore.com/security">
      <token>abc123</token>
    </authentication>
  </soap:Header>
  <soap:Body>
    <getCustomerName xmlns="http://CoCore.com/api">
      <customerId>456</customerId>
    </getCustomerName>
  </soap:Body>
</soap:Envelope>

GraphQL: Clean and direct

graphql
query {
  getCustomer(id: "456") {
    name
  }
}

2. Flexible Data Selection

XML/SOAP: Returns fixed structure

xml
<customer>
  <id>456</id>
  <name>John Doe</name>
  <email>john@example.com</email>
  <address>
    <street>123 Main St</street>
    <city>Springfield</city>
    <zip>12345</zip>
  </address>
  <preferences>
    <newsletter>true</newsletter>
    <smsUpdates>false</smsUpdates>
  </preferences>
  <orderHistory>
    <!-- Potentially hundreds of orders -->
  </orderHistory>
</customer>

GraphQL: Request only what you need

graphql
{
  getCustomer(id: "456") {
    name
    email
  }
}

3. Single Request for Complex Data

XML/SOAP: Multiple service calls

xml
<!-- First call: Get print job -->
<getPrintJob><jobId>123</jobId></getPrintJob>

<!-- Second call: Get customer details -->
<getCustomer><customerId>456</customerId></getCustomer>

<!-- Third call: Get assigned device -->
<getDevice><deviceId>789</deviceId></getDevice>

GraphQL: Single request

graphql
{
  getPrintJob(id: "123") {
    id
    title
    customer {
      name
      email
      recentOrders(limit: 3) {
        id
        total
      }
    }
    assignedDevice {
      name
      status
      currentJob {
        progress
      }
    }
  }
}

Migration Strategies

1. Gradual Migration

Start by wrapping existing XML services with GraphQL:

graphql
type Query {
  # New GraphQL endpoint
  getPrintJob(id: ID!): PrintJob

  # Legacy XML wrapper
  legacyGetPrintJobXML(jobId: String!): String
}

2. Schema-First Approach

Convert your XSD schemas to GraphQL schemas:

Before (XSD):

xml
<xs:complexType name="Device">
  <xs:sequence>
    <xs:element name="id" type="xs:string"/>
    <xs:element name="name" type="xs:string"/>
    <xs:element name="type" type="DeviceType"/>
    <xs:element name="status" type="DeviceStatus"/>
    <xs:element name="location" type="xs:string" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

After (GraphQL):

graphql
type Device {
  id: ID!
  name: String!
  type: DeviceType!
  status: DeviceStatus!
  location: String
}

enum DeviceType {
  DIGITAL_PRESS
  OFFSET_PRESS
  LARGE_FORMAT
  FINISHING
}

enum DeviceStatus {
  IDLE
  PRINTING
  MAINTENANCE
  ERROR
}

3. Error Handling Translation

SOAP Faults:

xml
<soap:Fault>
  <faultcode>Client.InvalidJobId</faultcode>
  <faultstring>Print job not found</faultstring>
  <detail>
    <errorCode>404</errorCode>
    <jobId>invalid123</jobId>
  </detail>
</soap:Fault>

GraphQL Errors:

json
{
  "errors": [
    {
      "message": "Print job not found",
      "extensions": {
        "code": "PRINT_JOB_NOT_FOUND",
        "jobId": "invalid123"
      },
      "path": ["getPrintJob"]
    }
  ],
  "data": {
    "getPrintJob": null
  }
}

Common XML Patterns in GraphQL

1. Namespaces → Schema Modules

XML Namespaces:

xml
<root xmlns:print="http://CoCore.com/print"
      xmlns:customer="http://CoCore.com/customer">
  <print:job>
    <customer:info>
      <customer:name>John</customer:name>
    </customer:info>
  </print:job>
</root>

GraphQL Modules:

graphql
# Organized by domain, not namespaces
type PrintJob {
  customer: Customer  # Clear relationships
}

type Customer {
  name: String
}

2. Attributes → Fields

XML Attributes:

xml
<printJob id="123" status="PRINTING" priority="HIGH">
  <title>Business Cards</title>
</printJob>

GraphQL Fields:

graphql
{
  getPrintJob(id: "123") {
    id
    status
    priority
    title
  }
}

3. Collections → Lists

XML Collections:

xml
<printJobs>
  <printJob id="1">...</printJob>
  <printJob id="2">...</printJob>
  <printJob id="3">...</printJob>
</printJobs>

GraphQL Arrays:

graphql
{
  printJobs {
    id
    title
    status
  }
}

Tooling Transition

From XML Editors to GraphQL

XML ToolsGraphQL Equivalents:

  • XMLSpy → GraphiQL/GraphQL Playground
  • SoapUI → Insomnia/Postman (with GraphQL support)
  • XSD Validation → Schema validation tools
  • XSLT → GraphQL resolvers/transformations

Authentication Migration

WS-Security (XML):

xml
<wsse:Security xmlns:wsse="...">
  <wsse:UsernameToken>
    <wsse:Username>user</wsse:Username>
    <wsse:Password Type="...">password</wsse:Password>
  </wsse:UsernameToken>
</wsse:Security>

GraphQL (HTTP Headers):

http
POST /graphql
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "query": "{ me { name } }"
}

Best Practices for XML Veterans

1. Think in Graphs, Not Hierarchies

XML Mindset: Deep nested structures

xml
<company>
  <departments>
    <department>
      <employees>
        <employee>
          <projects>
            <project>...</project>
          </projects>
        </employee>
      </employees>
    </department>
  </departments>
</company>

GraphQL Mindset: Connected data

graphql
{
  employees {
    name
    department {
      name
    }
    projects {
      title
      status
    }
  }
}

2. Embrace Type Safety

Your XML Schema validation skills translate directly to GraphQL's type system:

  • Required fields (! in GraphQL = minOccurs="1" in XSD)
  • Optional fields (nullable in GraphQL = minOccurs="0" in XSD)
  • Enums (same concept in both)
  • Custom scalar types (similar to XSD simple types)

3. Use Fragments Like XSD Includes

XSD Includes:

xml
<xs:include schemaLocation="customer.xsd"/>
<xs:include schemaLocation="address.xsd"/>

GraphQL Fragments:

graphql
fragment CustomerInfo on Customer {
  id
  name
  email
}

fragment AddressInfo on Address {
  street
  city
  country
}

query {
  getCustomer(id: "123") {
    ...CustomerInfo
    address {
      ...AddressInfo
    }
  }
}

CoCore-Specific Examples

Device Status Monitoring

Old XML/SOAP Approach:

xml
<soap:Envelope>
  <soap:Body>
    <getDeviceStatus>
      <deviceIds>
        <deviceId>printer1</deviceId>
        <deviceId>printer2</deviceId>
      </deviceIds>
    </getDeviceStatus>
  </soap:Body>
</soap:Envelope>

GraphQL Approach:

graphql
subscription DeviceUpdates {
  deviceStatusChanged(filter: {
    ids: ["printer1", "printer2"]
  }) {
    id
    name
    status
    currentJob {
      id
      progress
    }
    alerts {
      type
      message
      severity
    }
  }
}

Batch Operations

XML Batch:

xml
<batchRequest>
  <operations>
    <operation type="CREATE_JOB">
      <printJob>...</printJob>
    </operation>
    <operation type="UPDATE_STATUS">
      <jobId>123</jobId>
      <status>COMPLETED</status>
    </operation>
  </operations>
</batchRequest>

GraphQL Mutations:

graphql
mutation BatchOperations {
  createJob: createPrintJob(input: {...}) {
    result { id }
    errors { message }
  }

  updateStatus: updatePrintJob(
    id: "123"
    input: { status: COMPLETED }
  ) {
    result { status }
    errors { message }
  }
}

Conclusion

While XML/SOAP served the enterprise well for many years, GraphQL offers significant advantages for modern print shop management systems:

  • Less Complexity: No WSDL, no SOAP envelopes, no namespace management
  • Better Performance: Request exactly what you need
  • Real-time Capabilities: Built-in subscriptions for live updates
  • Developer Experience: Better tooling, introspection, and documentation

Your XML expertise translates well to GraphQL—the concepts of schemas, types, and validation are similar. The main shift is from document-centric thinking to graph-based, connected data models.

Start with simple queries, gradually migrate existing XML endpoints, and leverage GraphQL's flexibility to build more efficient integrations with CoCore's manufacturing systems.

Next Steps

Connect. Combine. Collaborate.
The pioneering open integration platform, dedicated to transforming connectivity in the printing industry.