我有一个我想要转换的xml文档:
<?xml version="1.0" encoding="UTF-8"?>
<import:configuration xmlns:import="http://schemas.company.com/wsdl/domain/v2/import">
<import:input>
<import:file headers="1" group="MAPPING">
<import:name>file001.txt</import:name>
<import:separator><![CDATA[;]]></import:separator>
<import:table>TAB00008_TECSPEC</import:table>
<import:field primary="true">
<import:name>VEMAR</import:name>
<import:target>VEMAR</import:target>
<import:type dbs="oracle" type="text">VARCHAR(3)</import:type>
<import:reference>
<import:table>TAB00006_TECSPEC</import:table>
<import:field>VEMAR</import:field>
</import:reference>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field primary="true">
<import:name>VENR</import:name>
<import:target>VENR</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(7)</import:type>
<import:reference>
<import:table>TAB00006_TECSPEC</import:table>
<import:field>VENR</import:field>
</import:reference>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field primary="true">
<import:name>KNR</import:name>
<import:target>KNR</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(9)</import:type>
<import:reference>
<import:table>TAB00003_TECSPEC</import:table>
<import:field>KNR</import:field>
</import:reference>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field>
<import:name>DATNEU</import:name>
<import:target>DATNEU</import:target>
<import:type dbs="oracle" type="date" format="YYYY.MM.DD">DATE</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field>
<import:name>VTYPE</import:name>
<import:target>VTYPE</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(1)</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:description><![CDATA[]]></import:description>
</import:file>
</import:input>
</import:configuration>
要:
<?xml version="1.0" encoding="UTF-8"?>
<import:configuration xmlns:import="http://schemas.company.com/wsdl/domain/v2/import">
<import:input>
<import:file headers="1" group="MAPPING">
<import:name>file001.txt</import:name>
<import:separator><![CDATA[;]]></import:separator>
<import:table>TAB00008_TECSPEC</import:table>
<import:field primary="true">
<import:name>VEMAR</import:name>
<import:target>VEMAR</import:target>
<import:type dbs="oracle" type="text">VARCHAR(3)</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field primary="true">
<import:name>VENR</import:name>
<import:target>VENR</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(7)</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field primary="true">
<import:name>KNR</import:name>
<import:target>KNR</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(9)</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field>
<import:name>DATNEU</import:name>
<import:target>DATNEU</import:target>
<import:type dbs="oracle" type="date" format="YYYY.MM.DD">DATE</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:field>
<import:name>VTYPE</import:name>
<import:target>VTYPE</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(1)</import:type>
<import:description><![CDATA[]]></import:description>
</import:field>
<import:reference>
<import:table>TAB00006_TECSPEC</table>
<import:link>
<source>VEMAR</source>
<target>VEMAR</target>
</import:link>
<import:link>
<source>VENR</source>
<target>VENR</target>
</import:link>
</import:reference>
<import:reference>
<import:table>TAB00003_TECSPEC</table>
<import:link>
<source>KNR</source>
<target>KNR</target>
</import:link>
</import:reference>
<import:description><![CDATA[]]></import:description>
</import:file>
</import:input>
</import:configuration>
我想对所有引用(</import:reference>
下的<import:field>
)进行分组,并按表格分组,将它们转换为一个元素,如上所述。
我正在阅读此帖子/问题:XML to CSV with XSLT - Grouping nodes但我无法通过此方式获得所需的输出。
我对xslt的了解不是很深。任何人都可以暗示我该怎么做?
答案 0 :(得分:1)
你的尝试太复杂了。我注意到的事情:
<xsl:copy>
和<xsl:copy-of>
制作输入节点的副本。您无需手动重新创建它们。您的任务是&#34;我需要输入文件的副本,但只需进行少量修改即可。多种。
这些任务的基础始终是身份转换。
<xsl:transform
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
这是输入的逐字副本。现在进行小修改。 XSLT通过模板匹配工作,因此我们需要<xsl:template>
来完成我们想要修改的所有内容。
您希望在最终输出中从<import:reference>
中删除<import:field>
。这很简单,为他们编写一个不产生输出的模板:
<xsl:template match="import:reference" />
您希望<import:reference>
内有一个新<import:file>
,每<import:table>
一个。这也不是那么困难。编写一个与import:file
匹配的模板,复制大部分模板并为每个import:table
组添加内容。
<xsl:template match="import:file">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:for-each-group select=".//import:reference" group-by="import:table">
<xsl:copy>
<xsl:copy-of select="import:table" />
<import:link>
<source><xsl:value-of select="../import:target" /></source>
<target><xsl:value-of select="import:field" /></target>
</import:link>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
把它放在一起:
<xsl:transform
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:import="http://schemas.company.com/wsdl/domain/v2/import"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="import:file">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:for-each-group select=".//import:reference" group-by="import:table">
<xsl:copy>
<xsl:copy-of select="import:table" />
<import:link>
<source><xsl:value-of select="../import:target" /></source>
<target><xsl:value-of select="import:field" /></target>
</import:link>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="import:reference" />
</xsl:transform>
产生几乎所需的结果:
<import:configuration xmlns:import="http://schemas.company.com/wsdl/domain/v2/import">
<import:input>
<import:file headers="1" group="MAPPING">
<import:name>file001.txt</import:name>
<import:separator>;</import:separator>
<import:table>TAB00008_TECSPEC</import:table>
<import:field primary="true">
<import:name>VEMAR</import:name>
<import:target>VEMAR</import:target>
<import:type dbs="oracle" type="text">VARCHAR(3)</import:type>
<import:description/>
</import:field>
<import:field primary="true">
<import:name>VENR</import:name>
<import:target>VENR</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(7)</import:type>
<import:description/>
</import:field>
<import:field primary="true">
<import:name>KNR</import:name>
<import:target>KNR</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(9)</import:type>
<import:description/>
</import:field>
<import:field>
<import:name>DATNEU</import:name>
<import:target>DATNEU</import:target>
<import:type dbs="oracle" type="date" format="YYYY.MM.DD">DATE</import:type>
<import:description/>
</import:field>
<import:field>
<import:name>VTYPE</import:name>
<import:target>VTYPE</import:target>
<import:type dbs="oracle" type="numeric">NUMBER(1)</import:type>
<import:description/>
</import:field>
<import:description/>
<import:reference>
<import:table>TAB00006_TECSPEC</import:table>
<import:link>
<source>VEMAR</source>
<target>VEMAR</target>
</import:link>
</import:reference>
<import:reference>
<import:table>TAB00003_TECSPEC</import:table>
<import:link>
<source>KNR</source>
<target>KNR</target>
</import:link>
</import:reference>
</import:file>
</import:input>
</import:configuration>
这不包括输出中的xmlns:xsi
属性(不是原始问题的一部分)。您可以通过编写修改import:configuration
:
<xsl:template match="import:configuration">
<xsl:copy>
<xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance">http://schemas.company.com/wsdl/domain/v2/import C:/Users/Ruben/Downloads/tmp/new/xsd/import_config.xsd</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
您可以将xsi
名称空间前缀声明移动到XSLT中的根级别。
答案 1 :(得分:0)
这有效(它使我接近我想要的目标):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://schemas.company.com/wsdl/domain/v2/import" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="ns0 xs fn">
<xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
<xsl:template match="/">
<configuration xmlns="http://schemas.company.com/wsdl/domain/v2/import">
<xsl:attribute name="xsi:schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance" select="'http://schemas.company.com/wsdl/domain/v2/import C:/Users/Ruben/Downloads/tmp/new/xsd/import_config.xsd'"/>
<xsl:for-each select="ns0:configuration">
<input>
<xsl:for-each select="ns0:input/ns0:file">
<xsl:variable name="var1_group" as="node()?" select="@group"/>
<file>
<xsl:attribute name="headers" namespace="" select="xs:string(xs:integer(fn:string(@headers)))"/>
<xsl:if test="fn:exists($var1_group)">
<xsl:attribute name="group" namespace="" select="fn:string($var1_group)"/>
</xsl:if>
<name>
<xsl:sequence select="fn:string(ns0:name)"/>
</name>
<xsl:for-each select="ns0:directory">
<directory>
<xsl:sequence select="fn:string(.)"/>
</directory>
</xsl:for-each>
<separator>
<xsl:sequence select="fn:string(ns0:separator)"/>
</separator>
<table>
<xsl:sequence select="fn:string(ns0:table)"/>
</table>
<xsl:for-each select="ns0:field">
<xsl:variable name="var2_primary" as="node()?" select="@primary"/>
<field>
<xsl:if test="fn:exists($var2_primary)">
<xsl:attribute name="primary" namespace="" select="xs:string(xs:boolean(fn:string($var2_primary)))"/>
</xsl:if>
<name>
<xsl:sequence select="fn:string(ns0:name)"/>
</name>
<target>
<xsl:sequence select="fn:string(ns0:target)"/>
</target>
<xsl:for-each select="ns0:type">
<type>
<xsl:sequence select="(./@node(), ./node())"/>
</type>
</xsl:for-each>
<description>
<xsl:sequence select="fn:string(ns0:description)"/>
</description>
</field>
</xsl:for-each>
<xsl:for-each select="ns0:field">
<xsl:variable name="var3_current" as="node()" select="."/>
<xsl:for-each select="ns0:reference">
<reference>
<table>
<xsl:sequence select="fn:string(ns0:table)"/>
</table>
<link>
<source>
<xsl:sequence select="fn:string($var3_current/ns0:target)"/>
</source>
<target>
<xsl:sequence select="fn:string(ns0:field)"/>
</target>
</link>
</reference>
</xsl:for-each>
</xsl:for-each>
<description>
<xsl:sequence select="fn:string(ns0:description)"/>
</description>
</file>
</xsl:for-each>
</input>
<description>
<xsl:sequence select="fn:string(ns0:description)"/>
</description>
</xsl:for-each>
</configuration>
</xsl:template>
</xsl:stylesheet>