问题
I have below xml and i need to convert to following xml using xslt
In the input xml i have referenced as topmost node which has subnodes as follows:
<?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>
Expected Output XML structure should be something like :
<?xml version="1.0"?>
<nodeInfo>
<name>PocTree/PocTree.services:getReferencesForServices</name>
<LOCK_STATUS>3</LOCK_STATUS>
<type>flow</type>
<path/>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>reference</status>
<children>
<name>WmRoot/wm.server.ns.dependency:getReferenced</name>
<LOCK_STATUS>2</LOCK_STATUS>
<type>java</type>
<path>/Flow Path;1.0/INVOKE;0</path>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>resolved</status>
</children>
<children>
<name>WmPublic/pub.xml:documentToXMLString</name>
<LOCK_STATUS>2</LOCK_STATUS>
<type>java</type>
<path>/Flow Path;1.0/INVOKE;1</path>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>resolved</status>
</reference>
<children>
<name>PocTree/PocTree.services:jkl</name>
<LOCK_STATUS>3</LOCK_STATUS>
<type>xsltservice</type>
<path>/Flow Path;1.0/INVOKE;2</path>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>resolved</status>
</children>
<children>
<name>WmPublic/pub.xml:xmlStringToXMLNode</name>
<LOCK_STATUS>2</LOCK_STATUS>
<type>java</type>
<path>/Flow Path;1.0/INVOKE;3</path>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>resolved</status>
</children>
<children>
<name>WmPublic/pub.xml:xmlNodeToDocument</name>
<LOCK_STATUS>2</LOCK_STATUS>
<type>java</type>
<path>/Flow Path;1.0/INVOKE;4</path>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>resolved</status>
</children>
<children>
<name>PocTree/PocTree.services:ghi</name>
<LOCK_STATUS>4</LOCK_STATUS>
<type>xsltservice</type>
<path>/Flow Path;1.0/INVOKE;5</path>
<isPub>false</isPub>
<isNotification>false</isNotification>
<isFlowServiceDisabled>false</isFlowServiceDisabled>
<status>resolved</status>
</children>
</nodeInfo>
But the criteria to obtain expected output xml is that from the value of one of the subnodes of input xml which is this section
<type>
<svc_type>flow</svc_type>
<svc_subtype>default</svc_subtype>
</type>
Which sometime does have a extra tag like this meaning can have either , child nodes or only .
<type>
<type_name>record</type_name>
</type>
Now the expected Output XML should be designed such way that chose only those <refrence>
tags from Input xml where <svc_type>
has value of 'flow' or 'javaservice' or 'xsltservice' and omit those <refrence>
tags which has <type_name>
belonging to <type>
parent node with any value.
Also the content of <svc_type>
should be mapped to value of <type>
and output xml should not contain subnodes <svc_type>
and <svc_subtype>
for its parent node <type>
.
Kindly help on this topic.
Including the xslt written to achieve filtering of input XML
<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[type/svc_type[contains(., 'flow') or contains(., 'java') or contains(., 'xsltservice')]]) and (reference[type/type_name[not(contains(.,'record'))]])">
<children>
<xsl:apply-templates />
</children>
</xsl:template>
</xsl:stylesheet>
But above xslt still does not cover this part -
<svc_type>
should be mapped to value of <type>
and output xml should not contain subnodes <svc_type>
and <svc_subtype>
for its parent node <type>
.
回答1:
You need to reverse your logic. Instead of thinking about what nodes you wish to copy, you need to think of what you don't want to copy, and write a template to match these, and ignore them.
The identity template will then handle all the things you want to copy.
So, you say you want to include <reference>
tags from Input xml where <svc_type>
has a value of 'flow' or 'javaservice' or 'xsltservice'. The converse of this is that you want to exclude such <reference>
which don't have a <svc_type>
set to any of those three values:
<xsl:template match="reference[type/svc_type[not(contains(., 'flow') or contains(., 'java') or contains(., 'xsltservice'))]]" />
You other rule is already one about removal, so that can be done straight-forwardly without any logic reversal
<xsl:template match="reference[type/type_name]" priority="2" />
The priority is probably not needed here, unless you could have a reference
tag which had both a type/type_name
and a type/svc_type
, in which case there would be a conflict between templates
Try this 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="reference[type/svc_type[not(contains(., 'flow') or contains(., 'java') or contains(., 'xsltservice'))]]" />
<xsl:template match="reference[type/type_name]" priority="2" />
</xsl:stylesheet>
Also note the addition of the template to turn to handle you transformation on svc_type
to just type
.
来源:https://stackoverflow.com/questions/40386383/xslt-with-identity-template-with-multiple-match-condition-and-removal-of-unused