Assuming you have some XML document, like
<data>
<episode-num system="onscreen">S1 E12</episode-num>
<episode-num system="onscreen">S1 S12</episode-num>
<episode-num system="onscreen">T1 S12</episode-num>
</data>
... and that you want to replace all S characters with T in the episode-num node values that start with S.
You do that with xmlstarlet like so:
xmlstarlet ed -u '//episode-num[starts-with(text(),"S")]' \
-x 'translate(text(),"S","T")' file.xml
This may modify any episode-num node, no matter where in the document these are located. If you only want to modify particular nodes, then change //episode-num in the XPath expression to a more precise path.
Given my example document above, the xmlstarlet command above would produce
<?xml version="1.0"?>
<data>
<episode-num system="onscreen">T1 E12</episode-num>
<episode-num system="onscreen">T1 T12</episode-num>
<episode-num system="onscreen">T1 S12</episode-num>
</data>
Doing the same sort of operation with xq (from https://kislyuk.github.io/yq/) as with xmlstarlet above:
xq -x '(.data."episode-num"[] | select (."#text"|startswith("S")))."#text" |= gsub("S";"T")' file.xml
This assumes that the input document has the same structure as my example document. It parses the document with an XML parser, and then translates it internally into JSON. It calls jq with the generated JSON document to apply the given expression, and finally translates everything back to XML again.
The internal JSON document that the jq expression is actually applied to looks like this, for the example document I'm using:
{
"data": {
"episode-num": [
{
"@system": "onscreen",
"#text": "S1 E12"
},
{
"@system": "onscreen",
"#text": "S1 S12"
},
{
"@system": "onscreen",
"#text": "T1 S12"
}
]
}
}