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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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 1.0使用逗号分隔值迭代多个XML元素_Xslt_Xpath - Fatal编程技术网

XSLT 1.0使用逗号分隔值迭代多个XML元素

XSLT 1.0使用逗号分隔值迭代多个XML元素,xslt,xpath,Xslt,Xpath,我有一个XML文档,其结构如下 <items> <item> <name>item1</name> <attributes>a,b,c,d</attributes> </item> <item> <name>item2</name> <attributes>c,d,e</attributes> </item> <

我有一个XML文档,其结构如下

<items>
 <item>
  <name>item1</name>
  <attributes>a,b,c,d</attributes>
 </item>
 <item>
  <name>item2</name>
  <attributes>c,d,e</attributes>
 </item>
</items>
我最初的计划是使用模板将属性解析为属性节点,用适当的标记围绕每个属性节点,然后用XPATH表达式(如

Attribute[not(.=following::Attribute)]
但是,由于模板的结果不是经过XML解析器的节点集,所以我无法遍历它。我还尝试了exslt的node-set()函数,只是为了实现它也不允许遍历单个属性节点


在这一点上,我不知道一个简单的方法来做这件事,并将非常感谢任何帮助或想法如何继续。谢谢

我的第一个想法是两次传球。首先,使用(稍加修改的)以下版本标记
属性
元素:


在一个样式表中执行此操作需要更多的思考(或扩展功能)。

此转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kAtrByVal" match="attr" use="."/>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <groups>
    <xsl:apply-templates/>
   </groups>
  </xsl:variable>

  <xsl:variable name="vPass1"
       select="ext:node-set($vrtfPass1)"/>

  <xsl:apply-templates select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="item">
  <group name="{name}">
   <xsl:apply-templates select="attributes"/>
  </group>
 </xsl:template>

 <xsl:template match="attributes" name="tokenize">
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText)">
   <xsl:variable name="vText" select=
        "concat($pText,',')"/>
   <attr>
    <xsl:value-of select="substring-before($vText,',')"/>
   </attr>
   <xsl:call-template name="tokenize">
    <xsl:with-param name="pText" select=
    "substring-after($pText,',')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>

 <xsl:template match=
  "attr[generate-id()
       =
        generate-id(key('kAtrByVal',.)[1])
       ]
  ">
  <xsl:value-of select="concat('&#xA;',.,': ')"/>

  <xsl:for-each select="key('kAtrByVal',.)">
   <xsl:value-of select="../@name"/>
   <xsl:if test="not(position()=last())">
    <xsl:text>, </xsl:text>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
<items>
    <item>
        <name>item1</name>
        <attributes>a,b,c,d</attributes>
    </item>
    <item>
        <name>item2</name>
        <attributes>c,d,e</attributes>
    </item>
</items>
说明

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kAtrByVal" match="attr" use="."/>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <groups>
    <xsl:apply-templates/>
   </groups>
  </xsl:variable>

  <xsl:variable name="vPass1"
       select="ext:node-set($vrtfPass1)"/>

  <xsl:apply-templates select="$vPass1/*"/>
 </xsl:template>

 <xsl:template match="item">
  <group name="{name}">
   <xsl:apply-templates select="attributes"/>
  </group>
 </xsl:template>

 <xsl:template match="attributes" name="tokenize">
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText)">
   <xsl:variable name="vText" select=
        "concat($pText,',')"/>
   <attr>
    <xsl:value-of select="substring-before($vText,',')"/>
   </attr>
   <xsl:call-template name="tokenize">
    <xsl:with-param name="pText" select=
    "substring-after($pText,',')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>

 <xsl:template match=
  "attr[generate-id()
       =
        generate-id(key('kAtrByVal',.)[1])
       ]
  ">
  <xsl:value-of select="concat('&#xA;',.,': ')"/>

  <xsl:for-each select="key('kAtrByVal',.)">
   <xsl:value-of select="../@name"/>
   <xsl:if test="not(position()=last())">
    <xsl:text>, </xsl:text>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
<items>
    <item>
        <name>item1</name>
        <attributes>a,b,c,d</attributes>
    </item>
    <item>
        <name>item2</name>
        <attributes>c,d,e</attributes>
    </item>
</items>
  • 过程1:标记化和最终结果:

  • 
    A.
    B
    C
    D
    C
    D
    E
    

    .2。Pass2将Pass1的结果(使用扩展函数
    ext:node-set()
    )转换为节点集)作为输入,执行Muenchian分组并生成最终的所需结果。

    好问题,+1。请参阅我的答案以获得完整的解决方案和解释。我喜欢思考这个问题,但仍然有一些问题。是否使用了
    以便在调用
    时,Muenchian分组模板可以完成它的工作?@ratherOCD:No,此模板只是覆盖用于文本节点的XSLT内置模板——并确保文本节点不会因
    而输出谢谢,我已经完成了所有工作。是否有一种按字母顺序排列属性的好方法?@ratherOCD:Yes,将
    xsl:apply templates select=“$vPass1/*/>
    替换为
    a : item1
    b : item1
    c : item1, item2
    d : item1, item2
    e : item2
    
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:msxsl="urn:schemas-microsoft-com:xslt"
     xmlns:ext="http://exslt.org/common">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:key name="kAtrByVal" match="attr" use="."/>
    
     <xsl:template match="/">
      <xsl:variable name="vrtfPass1">
       <groups>
        <xsl:apply-templates/>
       </groups>
      </xsl:variable>
    
      <xsl:variable name="vPass1"
           select="ext:node-set($vrtfPass1)"/>
    
      <xsl:apply-templates select="$vPass1/*"/>
     </xsl:template>
    
     <xsl:template match="item">
      <group name="{name}">
       <xsl:apply-templates select="attributes"/>
      </group>
     </xsl:template>
    
     <xsl:template match="attributes" name="tokenize">
      <xsl:param name="pText" select="."/>
    
      <xsl:if test="string-length($pText)">
       <xsl:variable name="vText" select=
            "concat($pText,',')"/>
       <attr>
        <xsl:value-of select="substring-before($vText,',')"/>
       </attr>
       <xsl:call-template name="tokenize">
        <xsl:with-param name="pText" select=
        "substring-after($pText,',')"/>
       </xsl:call-template>
      </xsl:if>
     </xsl:template>
    
     <xsl:template match=
      "attr[generate-id()
           =
            generate-id(key('kAtrByVal',.)[1])
           ]
      ">
      <xsl:value-of select="concat('&#xA;',.,': ')"/>
    
      <xsl:for-each select="key('kAtrByVal',.)">
       <xsl:value-of select="../@name"/>
       <xsl:if test="not(position()=last())">
        <xsl:text>, </xsl:text>
       </xsl:if>
      </xsl:for-each>
     </xsl:template>
    
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    
    <items>
        <item>
            <name>item1</name>
            <attributes>a,b,c,d</attributes>
        </item>
        <item>
            <name>item2</name>
            <attributes>c,d,e</attributes>
        </item>
    </items>
    
    a: item1
    b: item1
    c: item1, item2
    d: item1, item2
    e: item2
    
    <groups>
      <group name="item1">
        <attr>a</attr>
        <attr>b</attr>
        <attr>c</attr>
        <attr>d</attr>
      </group>
      <group name="item2">
        <attr>c</attr>
        <attr>d</attr>
        <attr>e</attr>
      </group>
    </groups>