我想使用xslt将两个xml文件合并为一个。
文件1:
<W>
<S event="idle" guid="328775aa-87fd-4f9c-b474-7b5d9d5a63b8" />
<S event="moving" guid="2db271fe-56c5-9ac8-9050-e2db2a653165" />
<S event="moving" guid="f90571fe-57f2-4204-9dd0-e2db2a634feb" />
<S event="moving" guid="4759ac82-d4f2-4fb3-9e60-36c531650cce" />
<S event="moving" guid="67450f05-eb20-4306-97aa-0357b9e83589" />
<S event="moving" guid="32f91c48-4865-48aa-a1c1-2a80b1b73cf6" />
<S event="idle" guid="33a06ae1-69a2-41f3-b295-663579b2477e" />
</W>
文件2:
<EpiVPED>
<vpeds guid="2db271fe-56c5-9ac8-9050-e2db2a653165" attachto="current">
<dp>
<name>Current</name>
</dp>
</vpeds>
<vpeds guid="f90571fe-57f2-4204-9dd0-e2db2a634feb" attachto="start">
<dp>
<name>Start</name>
</dp>
</vpeds>
<vpeds guid="4759ac82-d4f2-4fb3-9e60-36c531650cce" attachto="end">
<dp>
<name>End</name>
</dp>
</vpeds>
</EpiVPED>
合并:
<W>
<S event="idle" guid="328775aa-87fd-4f9c-b474-7b5d9d5a63b8">
<DataHandler>
<vpeds guid="f90571fe-57f2-4204-9dd0-e2db2a634feb" attachto="start">
<dp>
<name>Start</name>
</dp>
</vpeds>
</DataHandler>
</S>
<S event="moving" guid="2db271fe-56c5-9ac8-9050-e2db2a653165" >
<DataHandler>
<vpeds guid="2db271fe-56c5-9ac8-9050-e2db2a653165" attachto="current">
<dp>
<name>Current</name>
</dp>
</vpeds>
</DataHandler>
</S>
<S event="moving" guid="f90571fe-57f2-4204-9dd0-e2db2a634feb" >
<DataHandler />
</S>
<S event="moving" guid="4759ac82-d4f2-4fb3-9e60-36c531650cce" >
<DataHandler />
</S>
<S event="moving" guid="67450f05-eb20-4306-97aa-0357b9e83589" >
<DataHandler />
</S>
<S event="moving" guid="32f91c48-4865-48aa-a1c1-2a80b1b73cf6">
<DataHandler>
<vpeds guid="4759ac82-d4f2-4fb3-9e60-36c531650cce" attachto="end">
<dp>
<name>End</name>
</dp>
</vpeds>
</DataHandler>
</S>
<S event="idle" guid="33a06ae1-69a2-41f3-b295-663579b2477e">
<DataHandler />
</S>
</W>
如果满足以下条件,我需要将vpeds节点(文件2)复制到S节点(文件1)
1)将vpeds节点复制到S节点, 如果vped和S的引导都匹配 和 attachto ==当前
2)将vpeds节点复制到具有事件==空闲的先前的S中 如果vped和S的引导都匹配 和 attachto ==开始
3)将vpeds节点复制到具有事件==空闲的下一个S节点的直接S节点 如果vped和S的引导都匹配 和 attachto ==结束
我尝试了以下代码
在C#代码中,我将file1作为主要文件,将file2作为参数。
XmlDocument OutputGPSDoc= new XmlDocument();
XsltSettings xslsettings = new XsltSettings
{
EnableScript = true,
EnableDocumentFunction=true
};
XsltArgumentList _xslArg = new XsltArgumentList();
_xslArg.AddParam("vpedFilePath", "", @"D:\file2.xml");
XmlResolver secureResolver = new XmlSecureResolver(new XmlUrlResolver(), xslPath);
XslCompiledTransform oXslt = new XslCompiledTransform(true);
oXslt.Load(xslPath, xslsettings, secureResolver);
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.IgnoreWhitespace = true;
using (XmlReader reader = XmlReader.Create(@"D:\file1.xml", settings))
{
StringBuilder builder = new StringBuilder();
using (StringWriter stringWriter = new StringWriter(builder))
{
using (XmlWriter writer = XmlWriter.Create(stringWriter))
{
oXslt.Transform(reader, _xslArg, writer);
}
}
OutputGPSDoc.LoadXml(builder.ToString());
builder = null;
}
OutputGPSDoc.Save(@"D:\merged.xml");
下面的xslt代码是要进行转换
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:utils="urn:myExtension">
<xsl:output method="xml" encoding="utf-16" />
<xsl:param name="vpedFilePath"/>
<xsl:param name="updates" select="document($vpedFilePath)" />
<xsl:variable name="updateItems" select="$updates/EpiVPED/./*" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:strip-space elements="S" />
<xsl:template match="/">
<xsl:apply-templates select="/W" />
</xsl:template>
<xsl:template match="/W">
<xsl:element name="W">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="/W/S">
<xsl:element name="S">
<xsl:attribute name="event">
<xsl:value-of select= "@event" />
</xsl:attribute>
<xsl:variable name="GUID">
<xsl:value-of select= "@guid" />
</xsl:variable>
<xsl:attribute name="guid">
<xsl:value-of select= "$GUID" />
</xsl:attribute>
<xsl:element name="DataHandler">
<xsl:choose>
<xsl:when test="@event='idle'">
<!-- need to copy if satisfies the condition mentioned -->
</xsl:when>
<xsl:when test="following-sibling::S[1]/@event='idle'">
<!-- need to copy if satisfies the condition mentioned -->
</xsl:when>
<xsl:when test="$updateItems[@guid=$GUID and @attachto='2']">
<xsl:copy-of select="$updateItems[@guid=$Guid]"/>
</xsl:when>
</xsl:choose>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我不知道该怎么做。因为我是xslt的新手。有人有想法吗?我使用的是XSLT 1.0版。
答案 0 :(得分:1)
尝试一下
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:utils="urn:myExtension">
<xsl:output method="xml" encoding="utf-16" />
<xsl:param name="vpedFilePath"/>
<xsl:param name="updates" select="document($vpedFilePath)" />
<xsl:variable name="updateItems" select="$updates/EpiVPED/./*" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:strip-space elements="S" />
<xsl:variable name="stepCount" select="count(/W/S)"/>
<xsl:template match="/">
<xsl:apply-templates select="/W" />
</xsl:template>
<xsl:template match="/W">
<xsl:element name="W">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="/W/S">
<xsl:variable name="curIndex">
<xsl:number/>
</xsl:variable>
<xsl:variable name="CurrentStepEventName">
<xsl:value-of select="@event" />
</xsl:variable>
<xsl:variable name="FollowingStepStepEventName">
<xsl:value-of select="following-sibling::S[1]/@event" />
</xsl:variable>
<xsl:element name="S">
<xsl:variable name="GUID">
<xsl:value-of select= "@guid" />
</xsl:variable>
<xsl:attribute name="guid">
<xsl:value-of select= "@guid" />
</xsl:attribute>
<xsl:attribute name="event">
<xsl:value-of select= "@event" />
</xsl:attribute>
<xsl:element name="DataHandler">
<xsl:choose>
<xsl:when test="$CurrentStepEventName='idle'">
<xsl:variable name="vpedGUID" >
<xsl:call-template name="GetEntryStepVPEDGUID">
<xsl:with-param name="idx" select="1" />
<xsl:with-param name="curIndex" select="$curIndex" />
<xsl:with-param name="isCurStepProcessed" select="0" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="not($vpedGUID = '')">
<xsl:copy-of select="$updateItems[@guid = $vpedGUID]"/>
</xsl:if>
</xsl:when>
<xsl:when test="$FollowingStepStepEventName='idle'">
<xsl:variable name="vpedGUID" >
<xsl:call-template name="GetExitStepVPEDGUID">
<xsl:with-param name="idx" select="1" />
<xsl:with-param name="curIndex" select="$curIndex" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="not($vpedGUID = '')">
<xsl:copy-of select="$updateItems[@guid = $vpedGUID]"/>
</xsl:if>
</xsl:when>
<xsl:when test="$updateItems[@guid = $GUID and @attachto='current']">
<xsl:copy-of select="$updateItems[@guid = $GUID]"/>
</xsl:when>
</xsl:choose>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="GetEntryStepVPEDGUID">
<xsl:param name="idx" />
<xsl:param name="curIndex" />
<xsl:param name="isCurStepProcessed"/>
<xsl:variable name="followingStepGUID">
<xsl:choose>
<xsl:when test="not(($idx + $curIndex) >= $stepCount)">
<xsl:value-of select="following-sibling::S[$idx]/@guid"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="followingStepEvent">
<xsl:choose>
<xsl:when test="not(($idx + $curIndex) >= $stepCount)">
<xsl:value-of select="following-sibling::S[$idx]/@event"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="currentStepGUID">
<xsl:value-of select="@guid"/>
</xsl:variable>
<xsl:variable name="currentStepEvent">
<xsl:value-of select="@event"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$currentStepEvent = 'idle' and $updateItems[@guid = $currentStepGUID and (@attachto='start' or @attachto='current')] and $isCurStepProcessed = '0'">
<xsl:value-of select="$currentStepGUID"/>
<xsl:call-template name="GetEntryStepVPEDGUID">
<xsl:with-param name="idx" select="($idx)" />
<xsl:with-param name="curIndex" select="$curIndex" />
<xsl:with-param name="isCurStepProcessed" select="($isCurStepProcessed + 1)" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$followingStepEvent = 'idle' or ($idx + $curIndex) >= $stepCount">
</xsl:when>
<xsl:when test="$updateItems[@guid = $followingStepGUID and @attachto='start']">
<xsl:value-of select="$followingStepGUID"/>
<xsl:call-template name="GetEntryStepVPEDGUID">
<xsl:with-param name="idx" select="($idx + 1)" />
<xsl:with-param name="curIndex" select="$curIndex" />
<xsl:with-param name="isCurStepProcessed" select="($isCurStepProcessed + 1)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="GetEntryStepVPEDGUID">
<xsl:with-param name="idx" select="($idx + 1)" />
<xsl:with-param name="curIndex" select="$curIndex" />
<xsl:with-param name="isCurStepProcessed" select="($isCurStepProcessed + 1)" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="GetExitStepVPEDGUID">
<xsl:param name="idx" />
<xsl:param name="curIndex" />
<xsl:variable name="precedingStepGUID">
<xsl:choose>
<xsl:when test="not(($curIndex - $idx) <= 0)">
<xsl:value-of select="preceding-sibling::S[$idx]/@guid"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="precedingStepEvent">
<xsl:choose>
<xsl:when test="not(($curIndex - $idx) <= 0)">
<xsl:value-of select="preceding-sibling::S[$idx]/@event"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$precedingStepEvent = 'idle'">
<xsl:if test="$updateItems[@guid = $precedingStepGUID and @attachto='end']">
<xsl:value-of select="$precedingStepGUID"/>
</xsl:if>
</xsl:when>
<xsl:when test="($curIndex - $idx) <= 0"/>
<xsl:when test="$updateItems[@guid = $precedingStepGUID and @attachto='end']">
<xsl:value-of select="$precedingStepGUID"/>
<xsl:call-template name="GetExitStepVPEDGUID">
<xsl:with-param name="idx" select="($idx + 1)" />
<xsl:with-param name="curIndex" select="$curIndex" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="GetExitStepVPEDGUID">
<xsl:with-param name="idx" select="($idx + 1)" />
<xsl:with-param name="curIndex" select="$curIndex" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>