使用包含计数器的XSLT构建树结构

时间:2016-11-10 13:30:25

标签: xslt

我有xml以下,我需要使用我们已经实现的xslt转换为预期输出xml

在输入xml中,我引用了最顶层节点,其子节点如下:

    <?xml version="1.0"?>
<referenced>
  <name>PocTree/PocTree.services:getReferencesForServices</name>
  <LOCK_STATUS>3</LOCK_STATUS>
  <type>
    <svc_type>flow</svc_type>
    <svc_subtype>default</svc_subtype>
  </type>
  <path/>
  <isPub>false</isPub>
  <isNotification>false</isNotification>
  <isFlowServiceDisabled>false</isFlowServiceDisabled>
  <status>reference</status>
  <reference>
    <name>WmRoot/wm.server.ns.dependency:getReferenced</name>
    <LOCK_STATUS>2</LOCK_STATUS>
    <type>
      <svc_type>java</svc_type>
      <svc_subtype>unknown</svc_subtype>
    </type>
    <path>/Flow Path;1.0/INVOKE;0</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>resolved</status>
  </reference>
  <reference>
    <name>WmPublic/pub.xml:documentToXMLString</name>
    <LOCK_STATUS>2</LOCK_STATUS>
    <type>
      <svc_type>java</svc_type>
      <svc_subtype>unknown</svc_subtype>
    </type>
    <path>/Flow Path;1.0/INVOKE;1</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>resolved</status>
  </reference>
  <reference>
    <name>PocTree/PocTree.services:jkl</name>
    <LOCK_STATUS>3</LOCK_STATUS>
    <type>
      <svc_type>xsltservice</svc_type>
      <svc_subtype>unknown</svc_subtype>
    </type>
    <path>/Flow Path;1.0/INVOKE;2</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>resolved</status>
  </reference>
  <reference>
    <name>WmPublic/pub.xml:xmlStringToXMLNode</name>
    <LOCK_STATUS>2</LOCK_STATUS>
    <type>
      <svc_type>java</svc_type>
      <svc_subtype>unknown</svc_subtype>
    </type>
    <path>/Flow Path;1.0/INVOKE;3</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>resolved</status>
  </reference>
  <reference>
    <name>WmPublic/pub.xml:xmlNodeToDocument</name>
    <LOCK_STATUS>2</LOCK_STATUS>
    <type>
      <svc_type>java</svc_type>
      <svc_subtype>unknown</svc_subtype>
    </type>
    <path>/Flow Path;1.0/INVOKE;4</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>resolved</status>
  </reference>
  <reference>
    <name>PocTree/PocTree.services:ghi</name>
    <LOCK_STATUS>4</LOCK_STATUS>
    <type>
      <svc_type>xsltservice</svc_type>
      <svc_subtype>unknown</svc_subtype>
    </type>
    <path>/Flow Path;1.0/INVOKE;5</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>resolved</status>
  </reference>
  <reference>
    <name>WxPackageTree/WxPackageTree.doc:NodeInfo</name>
    <LOCK_STATUS>2</LOCK_STATUS>
    <type>
      <type_name>record</type_name>
    </type>
    <path>/Service Path;1.0/signature;2;subPath;"/nodes;4;0;WxPackageTree.doc:NodeInfo"</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>reference</status>
    <reference>
      <name>WxPackageTree/WxPackageTree.doc:NodeInfo</name>
      <LOCK_STATUS>2</LOCK_STATUS>
      <type>
        <type_name>record</type_name>
      </type>
      <path>/children;4;1;WxPackageTree.doc:NodeInfo</path>
      <isPub>false</isPub>
      <isNotification>false</isNotification>
      <isFlowServiceDisabled>false</isFlowServiceDisabled>
      <status>recursive</status>
    </reference>
    <reference>
    <name>PocTree/PocTree.docs:nodeInfo</name>
    <LOCK_STATUS>4</LOCK_STATUS>
    <type>
      <type_name>record</type_name>
    </type>
    <path>/Flow Path;1.0/MAP;6/MAPCOPY;1/to_field;-2;subPath;"/nodeInfo;4;0;PocTree.docs:nodeInfo"</path>
    <path>/Flow Path;1.0/MAP;6/MAPCOPY;2/to_field;-2;subPath;"/nodeInfo;4;0;PocTree.docs:nodeInfo"</path>
    <path>/Flow Path;1.0/MAP;6/MAPCOPY;3/to_field;-2;subPath;"/nodeInfo;4;0;PocTree.docs:nodeInfo"</path>
    <isPub>false</isPub>
    <isNotification>false</isNotification>
    <isFlowServiceDisabled>false</isFlowServiceDisabled>
    <status>reference</status>
    <reference>
      <name>PocTree/PocTree.docs:nodeInfo</name>
      <LOCK_STATUS>4</LOCK_STATUS>
      <type>
        <type_name>record</type_name>
      </type>
      <path>/children;4;1;PocTree.docs:nodeInfo</path>
      <isPub>false</isPub>
      <isNotification>false</isNotification>
      <isFlowServiceDisabled>false</isFlowServiceDisabled>
      <status>recursive</status>
    </reference>
  </reference>
  </reference>
</referenced> 

我们获得的预期输出XML:

 <?xml version="1.0" encoding="utf-8"?><nodeInfo>
  <name>PocTree/PocTree.services:getReferencesForServices</name>

  <type>flow</type>

  <isPub>false</isPub>



  <children>
    <name>WmRoot/wm.server.ns.dependency:getReferenced</name>

    <type>java</type>

    <isPub>false</isPub>



  </children>
  <children>
    <name>WmPublic/pub.xml:documentToXMLString</name>

    <type>java</type>

    <isPub>false</isPub>



  </children>
  <children>
    <name>PSUtilities2_3/PSUtilities.file:writeToFile</name>

    <type>java</type>


    <isPub>false</isPub>



  </children>
  <children>
    <name>PocTree/PocTree.services:jkl</name>

    <type>xsltservice</type>

    <isPub>false</isPub>



  </children>
  <children>
    <name>WmPublic/pub.xml:xmlStringToXMLNode</name>

    <type>java</type>

    <isPub>false</isPub>



  </children>
  <children>
    <name>WmPublic/pub.xml:xmlNodeToDocument</name>

    <type>java</type>

    <isPub>false</isPub>



  </children>
  <children>
    <name>PocTree/PocTree.services:ghi</name>

    <type>xsltservice</type>

    <isPub>false</isPub>



  </children>


  <children>
    <name>PocTree/PocTree.services:recursiveLoop</name>

    <type>flow</type>

    <isPub>false</isPub>



    <children>
      <name>WmPublic/pub.list:appendToDocumentList</name>

      <type>java</type>

      <isPub>false</isPub>



    </children>
    <children>
      <name>WmPublic/pub.xml:documentToXMLString</name>

      <type>java</type>

      <isPub>false</isPub>



    </children>
    <children>
      <name>PocTree/PocTree.services:ghi</name>

      <type>xsltservice</type>

      <isPub>false</isPub>



    </children>
    <children>
      <name>WmPublic/pub.list:appendToDocumentList</name>

      <type>java</type>



      <isPub>false</isPub>



    </children>


    <children>
      <name>PocTree/PocTree.services:recursiveLoop</name>

      <type>flow</type>

      <isPub>false</isPub>



    </children>
    <children>
      <name>PocTree/PocTree.services:recursiveLoop</name>

      <type>flow</type>

      <isPub>false</isPub>



    </children>
  </children>
</nodeInfo>

包括为实现上述输出XML结构而编写的xslt

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

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

    <xsl:template match="referenced">
        <nodeInfo>
            <xsl:apply-templates />
        </nodeInfo>
    </xsl:template>

    <xsl:template match="reference">
        <children>
            <xsl:apply-templates />
        </children>
    </xsl:template>

    <xsl:template match="type[svc_type]">
        <type>
            <xsl:value-of select="svc_type" />
        </type>
    </xsl:template>

    <xsl:template match="type[type_name]">
        <type>
            <xsl:value-of select="type_name" />
        </type>
    </xsl:template>

<xsl:template match="type[trigger_type]">
        <type>
            <xsl:value-of select="trigger_type" />
        </type>
    </xsl:template>

    <xsl:template match="reference[type/svc_type[not(contains(., 'flow') or contains(., 'java') or contains(., 'xsltservice') or contains(., 'spec'))]]" />


        <xsl:template match="reference[type/type_name[not(contains(., 'ConnectionData') or contains(., 'webServiceDescriptor'))]]" priority="2" />

<xsl:template match="reference[type/trigger_type[not(contains(., 'jms-trigger') or contains(., 'broker-trigger'))]]" priority="2" />

    <xsl:template match="LOCK_STATUS" />

    <xsl:template match="path" />

<xsl:template match="isNotification" />
<xsl:template match="isFlowServiceDisabled" />
<xsl:template match="status" />
</xsl:stylesheet>

现在我要求每个节点和子节点都应该有另外两个名为<rowId><parentNodeId>的标签。

因此,对于输出xml中的最顶层节点,<nodeInfo>将标记为<rowId>1</rowId><parentNodeId>0<parentNodeId>,并且<children>的子节点应再次具有<parentId>1<parentId>这些标签称为<rowId>2<rowId><parentId>,以此类推,表示有关父子关系的层次结构。最顶层节点的 <referenced> - - <reference> - - </reference> <reference> - - </reference> <reference> - - <reference> - - </reference> <reference> - - </reference> </reference> <reference> - - <reference> - - </reference> <reference> - - <reference> - - </reference> </reference> </reference> </referenced> 将从&#39; 0&#39;并且将从1开始并在遍历递归文档时递增1。

E.g。假设我的XML看起来像下面的

    <nodeInfo>
    <rowId>1</rowId>
    <parentNodeId>0</parentNodeId>
        <childen>
            -
            -
            <rowId>2</rowId>
            <parentNodeId>1</parentNodeId>
        </childen>
        <childen>
            -
            -
            <rowId>3</rowId>
            <parentNodeId>1</parentNodeId>
        </childen>
        <childen> 
            -
            -
            <rowId>4</rowId>
            <parentNodeId>1</parentNodeId>
                <childen>
                    -
                    -
                    <rowId>5</rowId>
                    <parentNodeId>4</parentNodeId>
                </childen>
                 <childen>
                    -
                    -
                    <rowId>6</rowId>
                    <parentNodeId>4</parentNodeId>
                </childen>
        </childen>
        <childen> 
          -
          -
          <rowId>7</rowId>
          <parentNodeId>1</parentNodeId>
            <childen>
                -
                -
                <rowId>8</rowId>
                <parentNodeId>7</parentNodeId>
            </childen>
            <childen>
                -
                -
                <rowId>9</rowId>
                <parentNodeId>7</parentNodeId>
                <childen>
                    -
                    -
                    <rowId>10</rowId>
                    <parentNodeId>9</parentNodeId>
                </childen>  
            </childen>
        </childen>
</nodeInfo>

应用XSLT之后,应该会出现类似这样的内容

<nodeInfo>
    -
    -
    <rowId>1</rowId>
    <parentNodeId>0</parentNodeId>
</nodeInfo>
<nodeInfo>
    -
    -
    <rowId>2</rowId>
    <parentNodeId>1</parentNodeId>
</nodeInfo>
<nodeInfo>
    -
    -
    <rowId>3</rowId>
    <parentNodeId>1</parentNodeId>
</nodeInfo>
<nodeInfo> 
    -
    -
    <rowId>4</rowId>
    <parentNodeId>1</parentNodeId>
</nodeInfo>
<nodeInfo>
    -
    -
    <rowId>5</rowId>
    <parentNodeId>4</parentNodeId>
</nodeInfo>
 <nodeInfo>
    -
    -
    <rowId>6</rowId>
    <parentNodeId>4</parentNodeId>
</nodeInfo>
<nodeInfo> 
    -
    -
    <rowId>7</rowId>
    <parentNodeId>1</parentNodeId>
</nodeInfo>
<nodeInfo>
    -
    -
    <rowId>8</rowId>
    <parentNodeId>7</parentNodeId>
</nodeInfo>
<nodeInfo>
    -
    -
    <rowId>9</rowId>
    <parentNodeId>7</parentNodeId>
</nodeInfo>
<nodeInfo>
    -
    -
    <rowId>10</rowId>
    <parentNodeId>9</parentNodeId>
</nodeInfo>

否则,在遍历Input xml之后,预期的输出也可能如下所示

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="x"/>

<xsl:template match="/">
    <root>
        <xsl:apply-templates select="referenced"/>
    </root>
</xsl:template>

<xsl:template match="referenced | reference">
    <nodeInfo>
        <xsl:copy-of select="name"/>
        <rowId>
            <xsl:value-of select="generate-id()"/>
        </rowId>
        <parentId>
            <xsl:value-of select="generate-id(..)"/>
        </parentId>

           <xsl:apply-templates select="type"/>

    </nodeInfo>
    <xsl:apply-templates select="reference"/>
</xsl:template>

 <xsl:template match="type[svc_type]">
        <type>
            <xsl:value-of select="svc_type" />
        </type>
    </xsl:template>

    <xsl:template match="type[type_name]">
        <type>
            <xsl:value-of select="type_name" />
        </type>
    </xsl:template>

<xsl:template match="type[trigger_type]">
        <type>
            <xsl:value-of select="trigger_type" />
        </type>
    </xsl:template>

    <xsl:template match="reference[type/svc_type[not(contains(., 'flow') or contains(., 'java') or contains(., 'xsltservice'))]]" />


    <xsl:template match="reference[type/type_name[not(contains(., 'ConnectionData') or contains(., 'webServiceDescriptor'))]]" priority="2" />

    <xsl:template match="reference[type/trigger_type[not(contains(., 'jms-trigger') or contains(., 'broker-trigger'))]]" priority="2" />

</xsl:stylesheet>

感谢您对此主题的帮助。

在您提供宝贵的意见和帮助之后,想出了这个XSLT - 让我知道这是否是这样做的最佳方式?

    $.validate({
        form : '#form',
        modules : 'file',
        validateOnBlur : false,
        borderColorOnError : 'red',
        inputParentClassOnError : 'error',
        scrollToTopOnError: false,
        errorMessageClass: 'text-error',

        onError : function() {

        },
        onSuccess: function($form) {
            // The input button is disabled if the form contains backend validations
            $form.find('input[type="submit"]').unbind('click');
            return true;
        }
    });

1 个答案:

答案 0 :(得分:0)

连续编号的ID有多重要?我怀疑你真正想要的是为每个节点提供一个唯一的 ID - 这可以通过使用generate-id()函数轻松实现:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="x"/>

<xsl:template match="/">
    <root>
        <xsl:apply-templates select="referenced"/>
    </root>
</xsl:template>

<xsl:template match="referenced | reference">
    <nodeInfo>
        <xsl:copy-of select="name"/>
        <rowId>
            <xsl:value-of select="generate-id()"/>
        </rowId>
        <parentNodeId>
            <xsl:value-of select="generate-id(..)"/>
        </parentNodeId>
        <type>
            <xsl:value-of select="type/svc_type | type/type_name | type/trigger_type" />
        </type>
    </nodeInfo>
    <xsl:apply-templates select="reference"/>
</xsl:template>

</xsl:stylesheet>

ID值本身取决于处理器;例如,使用libxslt将上述样式表应用于示例输入,结果将为:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <nodeInfo>
    <name>PocTree/PocTree.services:getReferencesForServices</name>
    <rowId>idp129115840</rowId>
    <parentNodeId>idp0</parentNodeId>
    <type>flow</type>
  </nodeInfo>
  <nodeInfo>
    <name>WmRoot/wm.server.ns.dependency:getReferenced</name>
    <rowId>idp129507904</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>java</type>
  </nodeInfo>
  <nodeInfo>
    <name>WmPublic/pub.xml:documentToXMLString</name>
    <rowId>idp49200</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>java</type>
  </nodeInfo>
  <nodeInfo>
    <name>PocTree/PocTree.services:jkl</name>
    <rowId>idp129175728</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>xsltservice</type>
  </nodeInfo>
  <nodeInfo>
    <name>WmPublic/pub.xml:xmlStringToXMLNode</name>
    <rowId>idp129088080</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>java</type>
  </nodeInfo>
  <nodeInfo>
    <name>WmPublic/pub.xml:xmlNodeToDocument</name>
    <rowId>idp129333520</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>java</type>
  </nodeInfo>
  <nodeInfo>
    <name>PocTree/PocTree.services:ghi</name>
    <rowId>idm2160</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>xsltservice</type>
  </nodeInfo>
  <nodeInfo>
    <name>WxPackageTree/WxPackageTree.doc:NodeInfo</name>
    <rowId>idp129139968</rowId>
    <parentNodeId>idp129115840</parentNodeId>
    <type>record</type>
  </nodeInfo>
  <nodeInfo>
    <name>WxPackageTree/WxPackageTree.doc:NodeInfo</name>
    <rowId>idp129142464</rowId>
    <parentNodeId>idp129139968</parentNodeId>
    <type>record</type>
  </nodeInfo>
  <nodeInfo>
    <name>PocTree/PocTree.docs:nodeInfo</name>
    <rowId>idp129145152</rowId>
    <parentNodeId>idp129139968</parentNodeId>
    <type>record</type>
  </nodeInfo>
  <nodeInfo>
    <name>PocTree/PocTree.docs:nodeInfo</name>
    <rowId>idp129148144</rowId>
    <parentNodeId>idp129145152</parentNodeId>
    <type>record</type>
  </nodeInfo>
</root>