<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; Jscript: вычисление пути к узлу XML]]></title>
		<link>http://forum.script-coding.com/viewtopic.php?id=9277</link>
		<atom:link href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=9277&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «Jscript: вычисление пути к узлу XML».]]></description>
		<lastBuildDate>Wed, 11 May 2022 15:17:06 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Jscript: вычисление пути к узлу XML]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=153173#p153173</link>
			<description><![CDATA[<p>Просматривая свои старые записи, наткнулся на код, заимствованный из этой темы. Обнаружил, что предложенная автором функция не работает если xml-узлы имеют полное имя (включают префикс, например, &lt;x:a /&gt;) и определение пространства имен для этого префикса.</p><p>Это легко исправить, если в запросах поиска узлов слева и справа использовать не nodeName, а baseName. Исправление представлено в функции selectXPath. Причем оно работоспособно и для первоначального примера.</p><p>Дополнительно реализовал функцию getXPath. Алгоритм отличается - там производится перебор всех предков и братьев узла средствами самого JS. Эффективность того или иного способа я не проверял.</p><p>Также, в обеих функциях добавил поддержку xml-атрибутов.</p><p>Функции возвращают корректные, но отличные друг от друга результаты.</p><div class="codebox"><pre><code>
var s = &#039;&lt;x:a xmlns:x=&quot;something&quot;&gt;&lt;b/&gt;&lt;b&gt;&lt;c/&gt;&lt;c id=&quot;1&quot;/&gt;&lt;/b&gt;&lt;/x:a&gt;&#039;;

var xml = new ActiveXObject(&#039;Msxml2.DOMDocument.6.0&#039;);
//xml.validateOnParse = true;
//xml.setProperty(&#039;SelectionLanguage&#039;, &#039;XPath&#039;);
xml.loadXML(s);

var a = xml.selectSingleNode(&#039;//@id&#039;);

var p1 = selectXPath(a); // returns &quot;/x:a/b[2]/c[2]/@id&quot;
var p2 = getXPath(a);    // returns &quot;/x:a[1]/b[2]/c[2]/@id&quot;

WScript.Echo(p1);
WScript.Echo(p2);

// http://forum.script-coding.com/viewtopic.php?id=9277
function selectXPath(xmlNode) {
	var result = [];

	var ancestors = xmlNode.selectNodes(&#039;ancestor-or-self::*&#039;)
	for (var i = 0; i &lt; ancestors.length; i++) {
		var node = ancestors[i];
		var nodeName = node.nodeName;
		var baseName = node.baseName;

		var L = node.selectNodes(&#039;preceding-sibling::&#039; + baseName).length;
		var R = node.selectNodes(&#039;following-sibling::&#039; + baseName).length;
		if ( L || R ) {
			nodeName += &#039;[&#039; + ( L + 1 ) + &#039;]&#039;;
		}
		result.push(nodeName);
	}

	// It&#039;s xml attribute. Store its name manually, because the code
	// above doesn&#039;t work for xml attributes.
	if ( xmlNode.nodeType == 2 ) {
		result.push(&#039;@&#039; + xmlNode.name);
	}

	return &#039;/&#039; + result.join(&#039;/&#039;)
};

// https://stackoverflow.com/a/18184670/3627676
function getXPath(xmlNode) {
	// It&#039;s xml attribute. Take its owner and continue.
	if ( xmlNode.nodeType == 2 ) {
		return arguments.callee(xmlNode.selectSingleNode(&#039;..&#039;)) +
			&#039;/@&#039; + xmlNode.name;
	}

	if ( xmlNode.parentNode == null ) {
		return &#039;&#039;;
	}

	var i = 1;
	for (var sibling = xmlNode; sibling = sibling.previousSibling; ) {
		if ( sibling.nodeName == xmlNode.nodeName ) {
			i++;
		}
	}

	return arguments.callee(xmlNode.parentNode) +
		&#039;/&#039; + xmlNode.nodeName + &#039;[&#039; + i + &#039;]&#039;;
};
</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Rumata)]]></author>
			<pubDate>Wed, 11 May 2022 15:17:06 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=153173#p153173</guid>
		</item>
		<item>
			<title><![CDATA[Re: Jscript: вычисление пути к узлу XML]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=80334#p80334</link>
			<description><![CDATA[<p>Писал заплатку для логического контроля принимаемых&nbsp; внешних файлов&nbsp; для которых<br />нет схем проверки xsd.&nbsp; Основная цель отсечь плохие файлы для загрузки в свое ППО.</p><p>Для ведения протокола ошибок (логирования предупреждений) была написана данная функция.</p><br /><div class="quotebox"><blockquote><p>20.02.2014 12:28:14 ****060625.xml<br />20.02.2014 12:28:14 Пусто:Information/DataArea/Header/Report/CardDataLine/Oper/NumberPP</p><p>20.02.2014 12:28:14 ****045631.xml<br />20.02.2014 12:28:14 Пусто:Information/DataArea/Header/Report/CardDataLine/Oper[2]/NameContragent<br />20.02.2014 12:28:14 Пусто:Information/DataArea/Header/Report/CardDataLine/Oper[2]/NumberPP</p></blockquote></div>]]></description>
			<author><![CDATA[null@example.com (badik)]]></author>
			<pubDate>Mon, 24 Feb 2014 03:38:53 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=80334#p80334</guid>
		</item>
		<item>
			<title><![CDATA[Re: Jscript: вычисление пути к узлу XML]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=80256#p80256</link>
			<description><![CDATA[<p>Собираюсь использовать подобный алгоритм для копирования в буфер обмена xPath из HTML (HTA) представления XML. Там, правда, ещё повозиться прийдётся: связать XML и представление. Соответственно, ознакомился с большим интересом.<br />Спасибо.</p>]]></description>
			<author><![CDATA[null@example.com (Serge Yolkin)]]></author>
			<pubDate>Fri, 21 Feb 2014 19:36:37 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=80256#p80256</guid>
		</item>
		<item>
			<title><![CDATA[Re: Jscript: вычисление пути к узлу XML]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=80252#p80252</link>
			<description><![CDATA[<p>Спасибо. <strong>badik</strong>, подскажите, а на практике в каких случаях она применимяется?</p>]]></description>
			<author><![CDATA[null@example.com (JSmаn)]]></author>
			<pubDate>Fri, 21 Feb 2014 15:17:19 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=80252#p80252</guid>
		</item>
		<item>
			<title><![CDATA[Jscript: вычисление пути к узлу XML]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=80174#p80174</link>
			<description><![CDATA[<p>Функция sPath вычисляет путь к конкретному узлу XML<br />Выражения xPath <br /></p><ul><li><p><strong>ancestor-or-self::*&nbsp; </strong>возращает родителей и сам узел</p></li><li><p><strong>preceding-sibling::</strong> узлы слева</p></li><li><p><strong>following-sibling:</strong>: узлы права</p></li></ul><div class="codebox"><pre><code>      var xd = new ActiveXObject(&quot;MSXML2.DOMDocument&quot;)
      xd.setProperty(&quot;SelectionLanguage&quot;, &quot;XPath&quot;)
      xd.async = false
      xd.loadXML(&#039;&lt;a&gt;&lt;b/&gt;&lt;b&gt;&lt;c/&gt;&lt;c id=&quot;1&quot;/&gt;&lt;/b&gt;&lt;/a&gt;&#039;)
      var o = xd.selectSingleNode(&quot;//c[@id=1]&quot;)
      WScript.Echo(sPath(o))
      // &gt;  a/b[2]/c[2]

  function sPath(xd) {
    var p = []
      if (xd)
      {
      var a = xd.selectNodes(&quot;ancestor-or-self::*&quot;)
      for (var i = 0; i &lt; a.length; i++) {
        p[p.length] = a[i].nodeName
        var nleft = (a[i].selectNodes(&quot;preceding-sibling::&quot; + a[i].nodeName)).length
        var nright = (a[i].selectNodes(&quot;following-sibling::&quot; + a[i].nodeName)).length
        if (nleft != 0 || nright != 0) {
          p[p.length - 1] += &quot;[&quot; + (nleft + 1) + &quot;]&quot;
        }
      }
    }
    return  p.join(&quot;/&quot;)
  }</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (badik)]]></author>
			<pubDate>Wed, 19 Feb 2014 03:21:25 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=80174#p80174</guid>
		</item>
	</channel>
</rss>
