powered by simpleCommunicator - 2.0.35     © 2025 Programmizd 02
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Выдернуть данные по неполному пути
7 сообщений из 7, страница 1 из 1
Выдернуть данные по неполному пути
    #39856688
zingerion
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть следующая структура xml(расписал один offer, остальные типовые)..задача стоит в том, чтобы я через командную строку Xpath-ом указывал, какой параметр мне нужно выдернуть относительно offer. То есть, это должно выглядеть так:
msxsl.exe Исходник.xml Стили.xsl -o Результат.csv SecondColumn=param[2]
или
msxsl.exe Исходник.xml Стили.xsl -o Результат.csv SecondColumn=price/Cat
<shop>
<offers>
<offer id="1" available="true">
<url> https://...</url>
<price>
<Cat>1</Cat>
<Cat>2</Cat>
</price>
<currencyId>RUR</currencyId>
<categoryId>1481</categoryId>
<picture>SomeURL.jpg</picture>
<name>Product</name>
<model>GJSER-1</model>
<vendor>Roomaif</vendor>
<description>Мягкие кожанные сандали<description>
<param>229</param>
<param>332</param>
<param name="Размер">26</param>
<barcode>4690507031995</barcode>
<offer>
.....
</offer>
<offer>
.....
</offer>
<offers>
<shop>


Мой xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl=" http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user=" http://www.contoso.com">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:param name="SecondColumn" select="SecondColumn"/>
<xsl:template match="offer">
<xsl:for-each select="msxsl:node-set($SecondColumn)">
<xsl:value-of select="." />
</xsl:for-each>
</xsl:template>

<xsl:template match="/">
<xsl:apply-templates select="yml_catalog/shop/offers/offer">
<xsl:with-param name="SecondColumn" />
</xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>

На выходе должен получиться csv файл
Плиз хэлп, не вижу вообще никакого решения, а в XSLT новичок
...
Рейтинг: 0 / 0
Выдернуть данные по неполному пути
    #39857164
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Принципиальная ошибка
zingerion
Код: xml
1.
<xsl:for-each select="msxsl:node-set($SecondColumn)">

$SecondColumn у вас строка и в набор узлов она не конвертируется. Чтобы из нее получить набор узлов нужно ее вручную распарсить и самому выполнить все XPath запросы.

Вторая ошибка
zingerion
Код: xml
1.
<xsl:output omit-xml-declaration="yes" indent="yes"/>

если вам на выходе нужен csv, то сообщите об этом процессору
Код: xml
1.
<xsl:output encoding="UTF-8" method="text"/>



Третья ошибка. Вот эта строка
zingerion
Код: xml
1.
<xsl:param name="SecondColumn" select="SecondColumn"/>

обозначает "Объявить параметр SecondColumn. А если его значение не было передано снаружи, то присвоить ему значение узла SecondColumn в текущем контексте. Такого узла у вас нет в принципе.

В итоге получилось вот так
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"  
  xmlns:user="http://www.contoso.com">
  
  <xsl:output encoding="UTF-8" method="text"/>
  
  <xsl:param name="SecondColumn"/>
  
  <xsl:template match="/">
    <xsl:apply-templates select="/shop/offers/offer"/>
  </xsl:template>
  
  <xsl:template match="offer">
    <xsl:apply-templates select="." mode="getNode">
      <xsl:with-param name="name" select="$SecondColumn"/>
    </xsl:apply-templates>
    <xsl:text>;
</xsl:text>
  </xsl:template>
  
  <xsl:template match="*" mode="getNode">
    <xsl:param name="name"/>
    <xsl:variable name="curName" select="substring-before($name, '/')"/>
    <xsl:choose>
      <xsl:when test="$curName != ''">
        <xsl:apply-templates select="*[local-name() = $curName]" mode="getNode">
          <xsl:with-param name="name" select="substring-after($name, '/')"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*[local-name() = $name]" mode="showNode"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  
  <xsl:template match="*" mode="showNode">
    <xsl:if test="position() &gt; 1">
      <xsl:text>,</xsl:text>
    </xsl:if>
    <xsl:value-of select="."/>
  </xsl:template>
</xsl:stylesheet>

...
Рейтинг: 0 / 0
Выдернуть данные по неполному пути
    #39857250
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще вариант решения, т.к. все равно используется MSXML написать на JS функцию, которая вернет набор узлов по указанному XPath

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"  
  xmlns:script="http://www.contoso.com/script"
  xmlns:user="http://www.contoso.com">
  
  <xsl:output encoding="UTF-8" method="text"/>
  
  <xsl:param name="SecondColumn"/>
  
  <xsl:template match="/">
    <xsl:apply-templates select="/shop/offers/offer"/>
  </xsl:template>
  
  <xsl:template match="offer">
    <xsl:apply-templates select="script:getNode(., $SecondColumn)" mode="showNode"/>
    <xsl:text>;
</xsl:text>
  </xsl:template>
  
  <msxsl:script language="JavaScript" implements-prefix="script">
    function getNode(parent, path) {
      return parent.item(0).selectNodes(path);
    }
  </msxsl:script>
  
  <xsl:template match="*" mode="showNode">
    <xsl:if test="position() &gt; 1">
      <xsl:text>,</xsl:text>
    </xsl:if>
    <xsl:value-of select="."/>
  </xsl:template>
</xsl:stylesheet>

тогда можно обойтись без ручного парсинга
...
Рейтинг: 0 / 0
Выдернуть данные по неполному пути
    #39857434
zingerion
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_,

Спасибо за ответ! $SecondColumn является строкой т к является глобальным параметром? Или из-за того, что передается в коммандной строке?
Я так понимаю, для подобного: param[2] нужно прописать отдельный template со своим mode?
...
Рейтинг: 0 / 0
Выдернуть данные по неполному пути
    #39857915
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zingerionИли из-за того, что передается в коммандной строке?Из-за этого. Из программы можно передать любой VARIANT
zingerionЯ так понимаю, для подобного: param[2] нужно прописать отдельный template со своим mode?Нет. Нужно дополнить парсинг в_Vasilisk_
Код: xml
1.
<xsl:template match="*" mode="getNode">



JS функция не подошла?
...
Рейтинг: 0 / 0
Выдернуть данные по неполному пути
    #39858051
zingerion
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_, нужно на чистом xslt, хотя решение на js работает
Воплотил замысел как-то так(убрал запяты, т к нужны "|", их я перенес в offer, т к помимо всего прочего нужно вывести offer id)
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"  
  xmlns:user="http://www.contoso.com">
  <xsl:output encoding="UTF-8" method="text"/>
  <xsl:param name="SecondColumn"/>
  
  <xsl:template match="/">
    <xsl:apply-templates select="yml_catalog/shop/offers/offer"/>
  </xsl:template>
  
  <xsl:template match="offer">
	<xsl:value-of select="@id" />
     <xsl:text>|</xsl:text>
    <xsl:apply-templates select="." mode="getNode">
      <xsl:with-param name="name" select="$SecondColumn"/>
    </xsl:apply-templates>
    <xsl:text>
</xsl:text>
  </xsl:template>
  
  <xsl:template match="*" mode="getNode">
    <xsl:param name="name"/>
    <xsl:variable name="curName" select="substring-before($name, '/')"/>
    <xsl:choose>
	       <xsl:when test="$curName != ''">
             <xsl:apply-templates select="*[local-name() = $curName]" mode="getNode">
               <xsl:with-param name="name" select="substring-after($name, '/')"/>
             </xsl:apply-templates>
           </xsl:when>
	       <xsl:otherwise>
	         <xsl:choose>
            <xsl:when test="substring-after($name, '[') != ''">
			   <xsl:variable name="number" select="substring-before($name,'[')" />
               <xsl:variable name="CurNumbName" select="number(substring-before(substring-after($name, '['), ']'))"/>
			   <xsl:apply-templates select="*[local-name() = $number]" mode="showNode">
			      <xsl:with-param name="ElemPosit" select="$CurNumbName" />
			   </xsl:apply-templates>
		    </xsl:when>
		   <xsl:otherwise>
		       <xsl:apply-templates select="*[local-name() = $name]" mode="showNode"/>
           </xsl:otherwise>
	    </xsl:choose>
	  </xsl:otherwise>
    </xsl:choose>
  </xsl:template> 
  
  <xsl:template match="*" mode="showNode">
    <xsl:param name="ElemPosit" /> 
	<xsl:choose>
	   <xsl:when test="$ElemPosit != '' ">
	     <xsl:if test="position()=$ElemPosit">
    	   <xsl:value-of select="." />
	     </xsl:if>
	   </xsl:when>
       <xsl:otherwise>
	      <xsl:value-of select="." /> 
	   </xsl:otherwise>
	</xsl:choose>
  </xsl:template>
</xsl:stylesheet>
...
Рейтинг: 0 / 0
Выдернуть данные по неполному пути
    #39858115
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот это
zingerion
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<xsl:choose>
  <xsl:when test="substring-after($name, '[') != ''">
    <xsl:variable name="number" select="substring-before($name,'[')" />
    <xsl:variable name="CurNumbName" select="number(substring-before(substring-after($name, '['), ']'))"/>
    <xsl:apply-templates select="*[local-name() = $number]" mode="showNode">
      <xsl:with-param name="ElemPosit" select="$CurNumbName" />
    </xsl:apply-templates>
  </xsl:when>
  <xsl:otherwise>
    <xsl:apply-templates select="*[local-name() = $name]" mode="showNode"/>
  </xsl:otherwise>
</xsl:choose>

делается так
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
<xsl:choose>
  <xsl:when test="substring-after($name, '[') != ''">
    <xsl:variable name="number" select="substring-before($name,'[')" />
    <xsl:variable name="CurNumbName" select="number(substring-before(substring-after($name, '['), ']'))"/>
    <xsl:apply-templates select="*[local-name() = $number] and position() = $CurNumbName" mode="showNode"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:apply-templates select="*[local-name() = $name]" mode="showNode"/>
  </xsl:otherwise>
</xsl:choose>
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Выдернуть данные по неполному пути
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]