为什么逗号在XSL嵌套for-each中没有按预期工作?

时间:2013-07-07 02:31:26

标签: json for-loop xslt-1.0 comma

TL; DR - 问题:在嵌套for-each中,我无法让逗号正确打印。有四种情况不断重复。我可以通过其他方式来完成工作,但我真的想知道为什么这样做会有所不同。

问题:为什么管道工作,但不是逗号,为什么最后一个元素有时会打印出来?

概述:我正在尝试将包含节点关系的XML文档转换为JSON格式,以便我可以进行图形可视化。有几种方法可以解决这个问题,我通过生成节点列表来选择开始。所以,我有一个XSL文件,它将XML文档转换为节点的JSON树结构。

以下是XML文件的摘录:

<?xml version="1.0" ?>
<knowledge_base
  xmlns="http://protege.stanford.edu/xml"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://protege.stanford.edu/xml http://www.enterprise-architecture.org/xml/essentialreportxml.xsd">
  <simple_instance>
    <name>Class181</name>
    <type>Business_Capability</type>
    <own_slot_value>
      <slot_reference>business_capability_level</slot_reference>
      <value value_type="string">3</value>
    </own_slot_value>
    <own_slot_value>
      <slot_reference>realised_by_business_processes</slot_reference>
      <value value_type="simple_instance">Class40041</value>
    </own_slot_value>
    <own_slot_value>
      <slot_reference>supports_business_capabilities</slot_reference>
      <value value_type="simple_instance">Class180</value>
      <value value_type="simple_instance">Class20022</value>
      <value value_type="simple_instance">Class182</value>
    </own_slot_value>
    <own_slot_value>
      <slot_reference>name</slot_reference>
      <value value_type="string">Help Desk Service</value>
    </own_slot_value>
  </simple_instance>
</knowledge_base>

有多种业务功能,他们可以将业务功能作为父级,将其他人作为子级。这是我的大部分XSL文档:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="2.0" xpath-default-namespace="http://protege.stanford.edu/xml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xalan="http://xml.apache.org/xslt" xmlns:pro="http://protege.stanford.edu/xml" xmlns:eas="http://www.enterprise-architecture.org/essential" xmlns:functx="http://www.functx.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ess="http://www.enterprise-architecture.org/essential/errorview">

  <xsl:template match="knowledge_base">
        <xsl:call-template name="BuildPage"/>
  </xsl:template>

  <xsl:template name="BuildPage">
    <xsl:param name="pageLabel">Business Capability Graph</xsl:param>
    <html>
      <head>
        <title><xsl:value-of select="$pageLabel"></xsl:value-of></title>
        <script src="js/d3.v3.min.js"></script>
        <script type="text/javascript">
          <xsl:text>
          function tree()
            {
            var json=</xsl:text><xsl:call-template name="getJSON" /><xsl:text>;
            console.log(JSON.stringify(json));
            }
        </xsl:text>
        </script>
        </head>
        <body onload="tree();">
          <div id="main"></div>
        </body>
        </html>
  </xsl:template>

  <xsl:template name="getJSON">
    <xsl:text>{ "nodes" : [</xsl:text>
    <!-- Get Business Caps -->
    <xsl:call-template name="getNodes">
      <xsl:with-param name="nodes" select="/node()/simple_instance[type='Business_Capability']" />
    </xsl:call-template>
    <xsl:text>]}</xsl:text>
  </xsl:template>

  <xsl:template name="getNodes">
    <xsl:param name="nodes" />
    <xsl:for-each select="$nodes">
      <xsl:variable name="name" select="own_slot_value[slot_reference='name']/value" />
      <xsl:variable name="id" select="current()/name" />
      <xsl:variable name="level" select="own_slot_value[slot_reference='business_capability_level']/value" />

      <xsl:text>{"name":"</xsl:text><xsl:value-of select="$name" />
      <xsl:text>", "id":"</xsl:text><xsl:value-of select="$id" />
      <xsl:text>", "level":"</xsl:text><xsl:value-of select="$level" />
      <xsl:text>", "data":{</xsl:text>

      <xsl:variable name="pcCap_list" select="own_slot_value[slot_reference='supports_business_capabilities']" />

      <xsl:text>"pcCap":{</xsl:text>
      <xsl:for-each select="/node()/simple_instance[name=$pcCap_list/value]" >
          <xsl:variable name="pos" select="position()" />
              <xsl:text>"id" : "</xsl:text>
              <xsl:value-of select="name" />
              <xsl:text> - pos </xsl:text><xsl:value-of select="$pos" />
              <xsl:text> - count </xsl:text><xsl:value-of select="count($pcCap_list/value)" />
              <xsl:text>"</xsl:text>
      </xsl:for-each>

      <xsl:text>}}}</xsl:text>
      <xsl:if test="position() != count($nodes)">
        <xsl:text>, </xsl:text>
      </xsl:if>

    </xsl:for-each>


  </xsl:template>

</xsl:stylesheet>

在整个文档中,我已成功使用xsl:if test=position() != count()在{{for-each内正确添加逗号(1,2,3), EXCEPT 1}}模板。我尝试了很多不同的变体,从使用position(),count(),last(),!=,&lt;,&gt;,=,not(position()= count()),count() - 1,count ()+1等,以及带有getNodesxsl:choose语句的xsl:when。我一直看到下面的四种模式(以及XSL语法错误和空对象)。

这是我尝试过的。所有内容都放在xsl:otherwise模板中内<xsl:text>"</xsl:text>的{​​{1}}和</xsl:for-each>之后。首先是XSL输入,我对发生的事情的总结,&amp;相关的JSON输出。

测试1:

for-each

测试2:

getNodes

测试3:

<xsl:if test="position() != count($pcCap_list/value)" >
  <xsl:text>, </xsl:text>
</xsl:if>

No XSL error.  No JS error.  But only **last element** is printed.

{
"name": "Help Desk Service",
"id": "Class181",
"level": "3",
"data": {
  "pcCap": {
    "id": "Class20022 - pos 3 - count 3"
  }
}
}

测试4:

<xsl:if test="position() = count($pcCap_list/value)" >
  <xsl:text>, </xsl:text>
</xsl:if>

No XSL error.  JS errors = "Uncaught SyntaxError: Unexpected string report:8" && "Uncaught ReferenceError: tree is not defined report:125".  All three are printed as expected with the comma after the third element.

{
  "name": "Help Desk Service",
  "id": "Class181",
  "level": "3",
  "data": {
    "pcCap": {
      "id": "Class180 - pos 1 - count 3""id": "Class182 - pos 2 - count 3""id": "Class20022 - pos 3 - count 3",

    }
  }
}

那么是什么导致管道工作而不是逗号?为什么第三个元素有时会自行打印?

1 个答案:

答案 0 :(得分:0)

您最初发布的转换适用于我的XSL转换器。我认为你的问题可能与变压器本身有关。我只是复制并粘贴了你的XML和XSL,并从XSLT获得了所需的输出。