Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 将源xml中的元素收集到内存中,在找到所有元素后输出_Xslt - Fatal编程技术网

Xslt 将源xml中的元素收集到内存中,在找到所有元素后输出

Xslt 将源xml中的元素收集到内存中,在找到所有元素后输出,xslt,Xslt,我有一个类似以下内容的源xml: <item> <id>1</id> <property name="representative_email"><value>Jallu.Kola@foo.bar.com</value></property> <property name="representative_name"><value>Jallu Kola</val

我有一个类似以下内容的源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>
<item>
    <id>
    <representatives>
        <representative>
            <email></email>
            <name></name>
            </phone></phone>
        </representative
    </representatives
</item>

1.
贾鲁。Kola@foo.bar.com
贾卢科拉
555 123 456
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
2.
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
3.
贾鲁。Kola@foo.bar.com
贾卢科拉
555 123 456
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
维尔。kalle@foo.bar.com
维尔卡尔
555 124 124124
不幸的是,除了使用xslt将其转换为更合理的内容之外,我对此无能为力。 我想把它转换成这样:

<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>
<item>
    <id>
    <representatives>
        <representative>
            <email></email>
            <name></name>
            </phone></phone>
        </representative
    </representatives
</item>


因此,如果每个组始终包含所有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>

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>

这里有一个更通用的解决方案,它也很短(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>
<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>

应用于提供的XML片段时(包装到单个顶部元素中,使其成为格式良好的XML文档):


1.
贾鲁。Kola@foo.bar.com
贾卢科拉
555 123 456
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
2.
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
3.
贾鲁。Kola@foo.bar.com
贾卢科拉
555 123 456
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
维尔。kalle@foo.bar.com
维尔卡尔
555 124 124124
生成所需的正确结果

<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>
<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.
贾鲁。Kola@foo.bar.com
贾卢科拉
555 123 456
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
2.
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
3.
贾鲁。Kola@foo.bar.com
贾卢科拉
555 123 456
萨拉。Rakas@foo.bar.com
萨拉拉卡斯
555 2314 124
维尔。kalle@foo.bar.com
维尔卡尔
555 124 124124
注意事项

<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>
<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>
  • 每个“代表”的属性数在外部提供的全局参数
    $pNumProps
    中指定

  • 要生成的元素的名称将自动生成(不是在接受的答案中硬编码),作为
    属性
    名称
    属性中“\u1”后面的字符串


  • 代表性道具是否总是以3为单位分组出现?或者有可能他们中的一些人失踪了?不幸的是,没有人保证他们是3人一组出现的。所以有可能他们中的一些人失踪了。他们中的一些人还是其中的任何一个?有一个总是出现吗?如果你有“email”然后是“name”。你怎么知道是一个代表同时拥有电子邮件和姓名,还是其中两个代表只有电子邮件,而第二个代表只有姓名?这看起来很不错,但不幸的是,我正在使用Xalan处理xml,它不支持这一点。也许你可以改为saxon(参见),更改Xalan的成本并没有那么高,XSLT 2.0是一种比XSLT 1.0强大得多的语言。谢谢。@kosoant:+1回答您的问题。您可能有兴趣看到一个更通用的解决方案,其中每个“代表”的元素名称和属性不是像此解决方案中那样硬编码的,而是可以从外部提供/动态计算的。:)