XPath Editor Online: Check the Namespace and the Result Type

HTML for this example

Select the code and use your copy shortcut. Changes in this preview are temporary.

<!doctype html>
<html lang="en-US"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>XPath Editor Online: Check the Namespace and the Result Type</title><style>:root{--bg:#edf1f5;--paper:#fff;--ink:#193449;--accent:#245d86;--tint:#dfeaf2;--line:#c4d0da;--muted:#40586a;--button:#fff}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:17px/1.55 system-ui,sans-serif}main{max-width:1000px;margin:auto;padding:22px clamp(18px,4vw,42px) 38px}header{border-bottom:2px solid var(--accent);padding-bottom:14px;margin-bottom:18px}h1{font-size:clamp(26px,4vw,36px);line-height:1.15;margin:4px 0 10px}h2{font-size:22px;line-height:1.3;margin:0 0 14px}h3{font-size:19px}p{margin:0 0 14px}.eyebrow{font-size:16px;font-weight:750;color:var(--accent)}.lede{max-width:800px}.panel{background:var(--paper);border:1px solid var(--line);border-radius:9px;padding:20px;margin:18px 0}.workbench{border-top:4px solid var(--accent)}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.grid>*{min-width:0}label{display:block;font-size:16px;font-weight:650;margin:12px 0 6px}input,textarea,select{font:inherit;color:var(--ink);background:var(--paper);border:1px solid #7b8893;border-radius:5px;padding:10px;width:100%;min-width:0}textarea{resize:vertical;line-height:1.45}input[type=checkbox],input[type=radio]{width:21px;height:21px;vertical-align:middle;margin-right:9px}button{font:650 16px/1.4 system-ui,sans-serif;padding:11px 15px;min-height:46px;background:var(--accent);border:2px solid var(--accent);color:var(--button);border-radius:5px;cursor:pointer}button:disabled{opacity:.55;cursor:default}.buttons{display:flex;gap:9px;flex-wrap:wrap;margin:14px 0}.buttons>*{flex:1 1 auto}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,summary:focus-visible{outline:3px solid #c05b00;outline-offset:3px}.result{font:600 17px/1.6 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;background:var(--tint);padding:16px;border-left:4px solid var(--accent);min-height:65px;margin:16px 0}.sample{padding:14px 16px;border-left:3px solid var(--accent);background:var(--tint);margin:12px 0}.muted{color:var(--muted)}pre,code{font:16px/1.6 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere}pre{margin:12px 0}table{border-collapse:collapse;width:100%;table-layout:fixed;font-size:16px}th,td{text-align:left;vertical-align:top;padding:10px 8px;border-bottom:1px solid var(--line);overflow-wrap:anywhere}th{background:var(--tint)}svg{max-width:100%;height:auto;display:block}details{margin:20px 0}summary{font-weight:700;cursor:pointer}footer{margin-top:28px;border-top:1px solid var(--line);padding-top:18px;font-size:16px}a{color:var(--accent)}.reading{font-family:Georgia,serif}.codeview{border-radius:0;box-shadow:7px 7px 0 var(--tint)}.token{display:inline-block;padding:8px 12px;margin:4px;border:1px solid var(--line);border-radius:4px;background:var(--paper)}.swatch{min-height:30px}.split{display:grid;grid-template-columns:1.1fr 1fr;gap:22px}ol{padding-left:25px}li{margin:9px 0}@media(max-width:600px){main{padding:16px}.grid,.split{grid-template-columns:1fr}.panel{padding:16px;margin:14px 0}h1{font-size:27px}header{padding-bottom:10px}.buttons{gap:8px}.result{padding:13px}th,td{padding:8px 5px}}header .lede{overflow-wrap:anywhere}</style></head><body><main><header><div class="eyebrow">Original practice fixture · local workbench</div><h1>Keep the namespace and the result type</h1><p class="lede">Bind prefix c to the catalog namespace, then compare node selections with number and string results. The XML fixture and expected checks appear below.</p></header><pre id="result" class="result" role="status" aria-live="polite" aria-atomic="true">Expected fixture: prefixed path selects 2 item elements; unprefixed path selects 0.</pre><label for="expression">XPath 1.0 expression</label><input id="expression" value="/c:catalog/c:item" ><label for="binding">Namespace URI for c</label><input id="binding" value="urn:demo:catalog" ><div class="buttons"><button type="button" id="evaluate">Evaluate</button><button type="button" id="clear">Clear workspace</button></div><label for="xml">XML source</label><textarea id="xml" rows="3" >&lt;catalog xmlns=&quot;urn:demo:catalog&quot;&gt;&lt;item code=&quot;A1&quot;&gt;0&lt;/item&gt;&lt;item code=&quot;A2&quot;&gt;7&lt;/item&gt;&lt;/catalog&gt;</textarea><section class="panel"><h2>Known typed checks</h2><p id="namespace-check">Bind c to urn:demo:catalog. /catalog/item selects 0 nodes; /c:catalog/c:item selects 2 item elements. A1 contains text "0" and A2 contains text "7".</p><p>count(/c:catalog/c:item) → Number 2</p><p>string(/c:catalog/c:item[1]) → String "0"</p><p>/c:catalog/c:item[2]/@code → attribute code = A2</p></section><footer><p>This uses browser XML/XPath 1.0 APIs, not schema validation, XSLT, remote retrieval, or XPath2/3.</p><p>Use a prepared HTML explanation in <a href="https://nos-workspace.com/">NOS</a> when reviewing this namespace-aware XPath 1.0 workbench. Eligible static instructions can be revised in visual editing mode; dynamic outputs follow their controls.</p></footer></main><script>
(()=>{'use strict';const $=s=>document.querySelector(s);const out=s=>{$('#result').textContent=s;};const val=id=>$('#'+id).value;const num=id=>{const s=val(id).trim();return s===''?NaN:Number(s);};const on=(id,fn)=>$('#'+id).addEventListener('click',fn);const watch=ids=>{for(const id of ids)for(const event of ['input','change'])$('#'+id).addEventListener(event,()=>out('Inputs changed. Run the action to update this result.'));};const fmt=(n,d=4)=>Math.abs(n)<1e-10?(0).toFixed(d):n.toFixed(d);
(function(){watch(['xml','expression','binding']);on('clear',()=>{for(const id of ['xml','expression','binding'])$('#'+id).value='';out('Not evaluated: empty workspace.');});on('evaluate',()=>{const xml=val('xml'),expression=val('expression'),uri=val('binding').trim();if(!xml.trim()||!expression.trim()){out('Not evaluated: XML and expression required.');return;}if(xml.length>10000||expression.length>1000){out('Limit: XML 10000 / expression 1000 UTF-16 units.');return;}if(/<!DOCTYPE|<!ENTITY|<\?/i.test(xml)){out('Unsupported XML construct: no DTD, entity declarations, or processing instructions.');return;}try{
// Validate every source in a detached XML context. Diagnostic names and text
// are valid user data and cannot identify a DOMParser failure.
try{
// The existing guard excludes declarations, DTDs and processing instructions.
// Preserve literal element boundaries: an XML fragment may otherwise accept
// outside references/text or omit an empty CDATA node.
const leading=xml.match(/^(?:\uFEFF)?(?:[ \t\r\n]|<!--(?:(?!-->)[\s\S])*-->)*/)[0];
const trailing=xml.slice(leading.length).match(/(?:[ \t\r\n]|<!--(?:(?!-->)[\s\S])*-->)*$/)[0];
const body=xml.slice(leading.length,xml.length-trailing.length);
if(!/^<[^!?/]/.test(body)||!/(?:\/>|<\/[^<>]+>)$/.test(body))throw new SyntaxError('Invalid document boundaries');
const context=document.implementation.createDocument(null,'_nos_fragment_context',null);
const range=context.createRange();range.selectNodeContents(context.documentElement);
const fragment=range.createContextualFragment(xml.replace(/^\uFEFF/,''));
let elements=0;for(const node of fragment.childNodes){
if(node.nodeType===1)elements++;
else if(node.nodeType!==8&&!(node.nodeType===3&&/^[ \t\r\n]*$/.test(node.nodeValue)))throw new SyntaxError('Invalid document misc');
}
if(elements!==1)throw new SyntaxError('Expected one source element');
}catch{out('XML parse error. Correct the source; no previous result retained.');return;}
// XPath keeps the original DOMParser document, never the validation fragment.
const doc=new DOMParser().parseFromString(xml,'application/xml');const resolver=prefix=>prefix==='c'&&uri?uri:null;let value=doc.evaluate(expression,doc,resolver,XPathResult.ANY_TYPE,null);if(value.resultType===XPathResult.NUMBER_TYPE){out('Number: '+String(value.numberValue));return;}if(value.resultType===XPathResult.STRING_TYPE){out('String: '+JSON.stringify(value.stringValue));return;}if(value.resultType===XPathResult.BOOLEAN_TYPE){out('Boolean: '+String(value.booleanValue));return;}value=doc.evaluate(expression,doc,resolver,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);if(value.snapshotLength>100){out('Result limit: more than 100 nodes; no partial complete result shown.');return;}const descriptions=[];for(let i=0;i<value.snapshotLength;i++){const n=value.snapshotItem(i);descriptions.push(n.nodeType===2?'attribute '+n.nodeName+'='+n.nodeValue:n.nodeType===1?'element '+n.nodeName+(n.getAttribute('code')?' code='+n.getAttribute('code'):'')+' text='+JSON.stringify(n.textContent):'text '+JSON.stringify(n.textContent));}out('Nodes: '+value.snapshotLength+(descriptions.length?' | '+descriptions.join(' | '):' (empty selection)'));}catch{out('XPath error: check expression and prefix bindings. No previous result retained.');}});})();
})();
</script></body></html>