Собирать элементы в память из исходного XML-файла, который будет выведен после того, как все найдены - PullRequest
1 голос
/ 25 ноября 2011

У меня есть исходный xml, который выглядит примерно так:

<item>
    <id>1</id>
    <property name="representative_email"><value>Jallu.Kola@foo.bar.com</value></property>
    <property name="representative_name"><value>Jallu Kola</value></property>
    <property name="representative_phone"><value>555 123 456</value></property>
    <property name="representative_email"><value>Sala.Rakas@foo.bar.com</value></property>
    <property name="representative_name"><value>Sala Rakas</value></property>
    <property name="representative_phone"><value>555 2314 124</value></property>
</item>
<item>
    <id>2</id>
    <property name="representative_email"><value>Sala.Rakas@foo.bar.com</value></property>
    <property name="representative_name"><value>Sala Rakas</value></property>
    <property name="representative_phone"><value>555 2314 124</value></property>
</item>
<item>
    <id>3</id>
    <property name="representative_email"><value>Jallu.Kola@foo.bar.com</value></property>
    <property name="representative_name"><value>Jallu Kola</value></property>
    <property name="representative_phone"><value>555 123 456</value></property>
    <property name="representative_email"><value>Sala.Rakas@foo.bar.com</value></property>
    <property name="representative_name"><value>Sala Rakas</value></property>
    <property name="representative_phone"><value>555 2314 124</value></property>
    <property name="representative_email"><value>ville.kalle@foo.bar.com</value></property>
    <property name="representative_name"><value>Ville Kalle</value></property>
    <property name="representative_phone"><value>555 124 124124</value></property>
</item>

К сожалению, я ничего не могу с этим поделать, кроме использования xslt для преобразования его в нечто более разумное.Я хотел бы преобразовать это, чтобы это выглядело так:

<item>
    <id>
    <representatives>
        <representative>
            <email></email>
            <name></name>
            </phone></phone>
        </representative
    </representatives
</item>

Любые идеи, как этого можно достичь с помощью xslt? Я думаю, что мне нужно собирать элементы представитель_ * в память при обработке элемента.Как только достигнут конец этого элемента элемента, я должен вывести новый элемент.В соответствии с этим мне нужно будет создать элемент для каждой группы элементов email + name + phone, которые появляются в последовательности.

Ответы [ 3 ]

1 голос
/ 25 ноября 2011

Решение XSLT 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output indent="yes"></xsl:output>
    <xsl:template match="*|@*">
        <xsl:copy>
            <xsl:apply-templates select="*|@*"/>            
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item">
        <xsl:copy>
            <xsl:copy-of select="id"/>
            <representatives>
                <xsl:for-each-group select="property" group-adjacent="count(preceding::*[@name=current()/@name])">
                    <representative>
                        <xsl:for-each select="current-group()">
                            <xsl:element name="{substring-after(@name,'_')}">
                                <xsl:value-of select="."></xsl:value-of>
                            </xsl:element>
                        </xsl:for-each>
                    </representative>
                </xsl:for-each-group>                
            </representatives>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

У вас должно быть имя свойства с '_' в нем. Он работает, беря в качестве первого представителя первую группу свойств, которые имеют другое имя в порядке документа, и продолжается так же для остальной части документа.

Я предполагаю наличие корня для вашего документа (с именем items). Результат XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<items>
   <item>
      <id>1</id>
      <representatives>
         <representative>
            <email>Jallu.Kola@foo.bar.com</email>
            <name>Jallu Kola</name>
            <phone>555 123 456</phone>
         </representative>
         <representative>
            <email>Sala.Rakas@foo.bar.com</email>
            <name>Sala Rakas</name>
            <phone>555 2314 124</phone>
         </representative>
      </representatives>
   </item>
   <item>
      <id>2</id>
      <representatives>
         <representative>
            <email>Sala.Rakas@foo.bar.com</email>
            <name>Sala Rakas</name>
            <phone>555 2314 124</phone>
         </representative>
      </representatives>
   </item>
   <item>
          <id>3</id>
      <representatives>
         <representative>
            <email>Jallu.Kola@foo.bar.com</email>
            <name>Jallu Kola</name>
            <phone>555 123 456</phone>
         </representative>
         <representative>
            <email>Sala.Rakas@foo.bar.com</email>
            <name>Sala Rakas</name>
            <phone>555 2314 124</phone>
         </representative>
         <representative>
            <email>ville.kalle@foo.bar.com</email>
            <name>Ville Kalle</name>
                <phone>555 124 124124</phone>
         </representative>
      </representatives>
   </item>
</items>
1 голос
/ 25 ноября 2011

Вот более общее решение, которое также является коротким (37 хорошо отформатированных строк) и простым :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNumProps" select="3"/>

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

 <xsl:template match="item">
  <item>
   <id><xsl:value-of select="id"/></id>
   <representatives>
    <xsl:apply-templates select=
     "property[position() mod $pNumProps = 1]"/>
   </representatives>
  </item>
 </xsl:template>

 <xsl:template match="property">
  <representative>
   <xsl:apply-templates mode="gen" select=
   ".|following-sibling::property
             [not(position() >= $pNumProps)]"/>
  </representative>
 </xsl:template>

 <xsl:template match="property" mode="gen">
  <xsl:element name="{substring-after(@name,'_')}">
   <xsl:value-of select="."/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному фрагменту XML (обернутый в один верхний элемент, чтобы сделать его правильно сформированным XML-документом):

<items>
 <item>
    <id>1</id>
    <property name="representative_email"><value>Jallu.Kola@foo.bar.com</value></property>
    <property name="representative_name"><value>Jallu Kola</value></property>
    <property name="representative_phone"><value>555 123 456</value></property>
    <property name="representative_email"><value>Sala.Rakas@foo.bar.com</value></property>
    <property name="representative_name"><value>Sala Rakas</value></property>
    <property name="representative_phone"><value>555 2314 124</value></property>
 </item>
 <item>
    <id>2</id>
    <property name="representative_email"><value>Sala.Rakas@foo.bar.com</value></property>
    <property name="representative_name"><value>Sala Rakas</value></property>
    <property name="representative_phone"><value>555 2314 124</value></property>
 </item>
 <item>
    <id>3</id>
    <property name="representative_email"><value>Jallu.Kola@foo.bar.com</value></property>
    <property name="representative_name"><value>Jallu Kola</value></property>
    <property name="representative_phone"><value>555 123 456</value></property>
    <property name="representative_email"><value>Sala.Rakas@foo.bar.com</value></property>
    <property name="representative_name"><value>Sala Rakas</value></property>
    <property name="representative_phone"><value>555 2314 124</value></property>
    <property name="representative_email"><value>ville.kalle@foo.bar.com</value></property>
    <property name="representative_name"><value>Ville Kalle</value></property>
    <property name="representative_phone"><value>555 124 124124</value></property>
 </item>
</items>

желаемый, правильный результат получается :

<items>
   <item>
      <id>1</id>
      <representatives>
         <representative>
            <email>Jallu.Kola@foo.bar.com</email>
            <name>Jallu Kola</name>
            <phone>555 123 456</phone>
         </representative>
         <representative>
            <email>Sala.Rakas@foo.bar.com</email>
            <name>Sala Rakas</name>
            <phone>555 2314 124</phone>
         </representative>
      </representatives>
   </item>
   <item>
      <id>2</id>
      <representatives>
         <representative>
            <email>Sala.Rakas@foo.bar.com</email>
            <name>Sala Rakas</name>
            <phone>555 2314 124</phone>
         </representative>
      </representatives>
   </item>
   <item>
      <id>3</id>
      <representatives>
         <representative>
            <email>Jallu.Kola@foo.bar.com</email>
            <name>Jallu Kola</name>
            <phone>555 123 456</phone>
         </representative>
         <representative>
            <email>Sala.Rakas@foo.bar.com</email>
            <name>Sala Rakas</name>
            <phone>555 2314 124</phone>
         </representative>
         <representative>
            <email>ville.kalle@foo.bar.com</email>
            <name>Ville Kalle</name>
            <phone>555 124 124124</phone>
         </representative>
      </representatives>
   </item>
</items>

Примечание: :

  1. Количество свойств на «представителя» указывается во внешнем глобальном параметре $pNumProps.

  2. Имя генерируемого элемента создается автоматически (не жестко, как в принятом ответе) в виде строки, следующей за '_' в атрибуте name для property.

1 голос
/ 25 ноября 2011

Таким образом, если каждая группа всегда содержит все 3 элемента, вы можете перебрать один из них, а затем выбрать другие в той же позиции:

<xsl:template match="item">
  <item>
    <xsl:copy-of select="id"/>
    <representatives>
      <xsl:apply-templates select="property[@name='representative_email']"/>
    </representatives>
  </item>
</xsl:template>
<xsl:template match="property">
  <representative>
    <email>
      <xsl:value-of select="../property[@name='representative_email'][position()]"/>
    </email>
    <name>
      <xsl:value-of select="../property[@name='representative_name'][position()]"/>
    </name>
    <phone>
      <xsl:value-of select="../property[@name='representative_phone'][position()]"/>
    </phone>
  </representative>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...