2014-02-14 3 views
0

Мне нужно перевести XML из исходного формата в пары значений целевого имени для общей обработки. Любые советы о том, как этого достичь, пожалуйста? Я пытаюсь использовать MapForce, если это проще.XSLT - Как сопоставить элементы для определения пар значений?

От

<products> 
    <product> 
     <type>Monitor</type> 
     <size>22</size> 
     <brand>EIZO</brand> 
    </product> 
    <product> 
     ...... 
    </product> 
</products> 

в

<products> 
    <product num="1"> 
     <attribute name="type">Monitor</attribute> 
     <attribute name="size">22</attribute> 
     <attribute name="brand">EIZO</attribute> 
    </product> 
    <product num="2"> 
     .... 
    </product> 
</products> 

Я предполагаю, что нужно использовать XSL: для каждого-в элементе для создания элемента?

Как насчет атрибута «num», это просто счетчик в основном. Может ли это быть позиция()?

Большое спасибо!

+0

Просто убедитесь, что вы правильно поняли вопрос: уверены, что вас не просили превратить его в ' '? Это то, что «атрибут» обычно означает в XML. – keshlam

ответ

-1

Не проверял, но вы могли бы сделать что-то вроде следующего:

<products> 
    <xsl:for-each select="//product"> 
     <product num="{position()}"> 
      <xsl:for-each select="current()/*"> 
      <attribute name="{name()}"> 
       <xsl:value-of select="self::node()/text()"/> 
      </attribute> 
      </xsl> 
     </product> 
    </xsl> 
</products> 
0

Я думаю, что у меня есть то, что вы ищете. Нет для каждого предложения. Просто магия рекурсивных шаблонов:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="xml" indent="yes"/> 

<xsl:template match="products"> 
    <products> 
     <xsl:call-template name="transformProducts"> 
      <xsl:with-param name="nodes" select="product"/> 
     </xsl:call-template> 
    </products> 
</xsl:template> 

<xsl:template name="transformProducts"> 
    <xsl:param name="nodes"/> 
    <xsl:param name="counter" select="0"/> 

    <xsl:choose> 
     <xsl:when test="not($nodes)"></xsl:when> 
     <xsl:otherwise> 
      <product> 
       <xsl:attribute name="num"> 
        <xsl:value-of select="$counter + 1"/> 
       </xsl:attribute> 
       <xsl:attribute name="type"> 
        <xsl:value-of select="$nodes[1]/type"/> 
       </xsl:attribute> 
       <xsl:attribute name="size"> 
        <xsl:value-of select="$nodes[1]/size"/> 
       </xsl:attribute> 
       <xsl:attribute name="brand"> 
        <xsl:value-of select="$nodes[1]/brand"/> 
       </xsl:attribute> 
      </product> 
      <xsl:call-template name="transformProducts"> 
       <xsl:with-param name="nodes" select="$nodes[position() > 1]"/> 
       <xsl:with-param name="counter" select="$counter + 1"/> 
      </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

Согласно моему тесту, вот исходный XML:

<products>  
<product> 
    <type>Monitor</type> 
    <size>22</size> 
    <brand>EIZO</brand> 
</product> 
<product> 
    <type>MonitorTwo</type> 
    <size>32</size> 
    <brand>SONY</brand> 
</product> 
<product> 
    <type>what</type> 
    <size>12</size> 
    <brand>VGA</brand> 
</product> 
</products> 

А вот выход. Я предполагаю, назвав ваши атрибуты «элементами», которые вы на самом деле означали для их преобразования в узлы атрибутов элемента продукта?

<products> 
<product num="1" type="Monitor" size="22" brand="EIZO"/> 
<product num="2" type="MonitorTwo" size="32" brand="SONY"/> 
<product num="3" type="what" size="12" brand="VGA"/> 
</products> 
+0

"* Нет для каждого предложения. *" Вы говорите, что это хорошо, но вы только что сделали очень хорошую работу, чтобы доказать обратное. –

+0

Кстати, вы предполагаете, что каждый продукт имеет точно такой же набор атрибутов {type; размер; бренд}, в то время как OP достаточно четко определил «пары значений имени для общей обработки». –

+0

Нет, нет ничего плохого в использовании предложения for-each. На самом деле это выглядит как более простое решение. Но в рекурсивном решении нет ничего плохого. Однако вы правильно указали, что я забыл слово «родовое» в вопросе. Если бы не было достаточно ответов, я бы отредактировал мой. –

2

Для таких проблем, как это часто начинается с созданием шаблона идентичности XSLT

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

На своей собственной этой копии всех узлы как есть, это означает, что вам нужно только написать соответствующие шаблоны для узлов вы хотите преобразовать.

Для начала, вы хотите добавить Num атрибут в продукта, так что есть шаблон, соответствующий продукт где вы просто вывести его с атрибутом и продолжить обработку своих детей.

<xsl:template match="product"> 
    <product num="{position()}"> 
     <xsl:apply-templates select="@*|node()"/> 
    </product> 
</xsl:template> 

Обратите внимание на использование значения атрибута шаблонов здесь, в создании Num атрибут . В фигурных скобках указано выражение, которое должно быть оценено, а не выводиться буквально.

Затем вы хотите шаблон, чтобы соответствовать детей в продукции элементов, и превратить их в атрибут узлов. Это делается с помощью шаблона, чтобы соответствовать любому такому ребенку, как так

<xsl:template match="product/*"> 
    <attribute name="{local-name()}"> 
     <xsl:apply-templates /> 
    </attribute> 
</xsl:template> 

Обратите внимание, что <xsl:apply-templates /> может быть заменен <xsl:value-of select="." /> здесь, если вы только когда-либо будешь иметь текстовые узлы в пределах дочерних элементов.

Попробуйте XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="product"> 
     <product num="{position()}"> 
     <xsl:apply-templates select="@*|node()"/> 
     </product> 
    </xsl:template> 

    <xsl:template match="product/*"> 
     <attribute name="{local-name()}"> 
     <xsl:apply-templates /> 
     </attribute> 
    </xsl:template> 
</xsl:stylesheet> 

Применительно к вашему XML следующего выводится

<products> 
    <product num="1"> 
    <attribute name="type">Monitor</attribute> 
    <attribute name="size">22</attribute> 
    <attribute name="brand">EIZO</attribute> 
    </product> 
    <product num="2"> 
     ...... 
    </product> 
</products> 

Конечно, если делать на самом деле хочет, чтобы включить дочерние элементы в соответствующие атрибуты, в отличии от элементов named "attribute", вы должны использовать команду xsl: attribute. Заменить последний шаблон с этим

<xsl:template match="product/*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
</xsl:template> 

При использовании этого шаблона вместо, следующий вывод (ну, это будет включать в себя продукт 2, если ваш образец имеет дочерние элементы для него!)

<products> 
    <product num="1" type="Monitor" size="22" brand="EIZO"></product> 
    <product num="2"> 
    ...... 
    </product> 
</products> 
0

Конечно , небеса запрещают, чтобы это было коротко и просто, потому что ... почему?

Вариант А (элементы с именем "атрибут"):

<xsl:template match="/"> 
<products> 
    <xsl:for-each select="products/product"> 
     <product num="{position()}"> 
      <xsl:for-each select="*"> 
      <attribute name="{name()}"> 
       <xsl:value-of select="."/> 
      </attribute> 
      </xsl:for-each> 
     </product> 
    </xsl:for-each> 
</products> 
</xsl:template> 

Version B (реальные атрибуты):

<xsl:template match="/"> 
<products> 
    <xsl:for-each select="products/product"> 
     <product num="{position()}"> 
      <xsl:for-each select="*"> 
      <xsl:attribute name="{name()}"> 
       <xsl:value-of select="."/> 
      </xsl:attribute> 
      </xsl:for-each> 
     </product> 
    </xsl:for-each> 
</products> 
</xsl:template> 
0

Спасибо всем,

И Тим и Филлипс подходы очень разные, но обе работают отлично. Имею ли я право думать

  • Подход Тима основан на исходном XML, а затем использует шаблоны, чтобы настроить все, что указано. Скажем, если у меня есть 100 элементов и только хочу подстроить несколько, то это хорошо.

  • Подход Phillip - это создание нового XML с нуля, но XPath-ing/извлечение того, что я хочу. Скажем, если у меня есть 100 элементов, и я только хочу извлечь и преобразовать несколько, как для вывода, то это хорошо.

Большое спасибо!

 Смежные вопросы

  • Нет связанных вопросов^_^