我花了很多时间试图解决这个问题,而失败并没有提供任何关于错误的线索。我正在尝试使用xslt进行项目。显然,我正在尝试使用2.0,这是来自VS 2012,c#fw 4.5
对于此测试,如果值为0,我想用任何内容替换任何xxxSK元素的值。
这适用于以下元素:,等等。
如果我将底部模板定位到“SK”,则会将其正确应用于所有模板。但我希望“结束”逻辑(或在此示例中为“包含”)。当我运行这个时,我在调用Transform()时得到一条无用的消息:
System.InvalidProgramException was unhandled
HResult=-2146233030
Message=Common Language Runtime detected an invalid program.
Source=System.Xml.Xsl.CompiledQuery.1
StackTrace:
at <xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator )
at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer)
at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver)
at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, Stream results)
at Test.XsltTest.Test(Drug drug, String styleSheet) in c:\DEV\Local Projects\_JunkTempWork\AppToSQLDataTransferTesting\Test\XsltTest.cs:line 34
at Test.Program.Main(String[] args) in c:\DEV\Local Projects\_JunkTempWork\AppToSQLDataTransferTesting\Test\Program.cs:line 28
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
[这里有一个类似的问题] [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" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[matches(name(), '.*SK')]"> <--- ORIGINAL QUESTION
<xsl:template match="*[substring(name(), string-length() -1) = 'SK']" priority="9"> <--- NEW BASED ON ANSWER
<xsl:text disable-output-escaping="yes"><New</xsl:text><xsl:value-of select="name(.)"/> <xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:if test=". != '0'">
<xsl:value-of select="."/>
</xsl:if>
<xsl:text disable-output-escaping="yes"></New</xsl:text><xsl:value-of select="name(.)"/><xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
</xsl:stylesheet>
这是我的测试代码(模型只是一个简单的测试类):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Serialization;
using Test.Models;
using System.Xml;
using System.Xml.Xsl;
namespace Test
{
public class XsltTest
{
public string Test(Drug drug, string styleSheet)
{
//ListResources(); return string.Empty;
// Serialize
Console.WriteLine("Serialized:");
string xml = XmlSerialization.Serialize(drug);
// Load into XML DOC
var xd = new XmlDocument();
xd.LoadXml(xml);
// Load XSLT DOC
var xslt = GetTransform(styleSheet);
using (var stm = new MemoryStream())
{
// Transform!
xslt.Transform(xd, null, stm);
// Fetch the results
stm.Position = 1;
using (var sr = new StreamReader(stm))
{
string result = "\nSource:\n\n" + xml + "\n\nOutput:\n\n" + sr.ReadToEnd();
return result;
}
}
}
private void ListResources()
{
string[] resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
foreach (string r in resources)
Console.WriteLine("Resource: {0}", r);
}
private XslCompiledTransform GetTransform(string styleSheet)
{
if (!Assembly.GetExecutingAssembly().GetManifestResourceNames().Contains(styleSheet))
throw new Exception(string.Format("Stylesheet {0} not found.", styleSheet));
using (Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(styleSheet))
{
using (XmlReader reader = XmlReader.Create(s))
{
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(reader);
return transform;
}
}
}
}
}
更新:感谢回复,我得到了部分工作。任何人都可以看到它为什么不匹配所有元素?正如你所看到的那样,它只与2个元素相匹配,即便如此,我也看不出它选择这些元素的原因,而不是其他元素。
输入XML:
<?xml version="1.0" encoding="utf-16"?>
<Drug xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SK>0</SK>
<MasterSK>0</MasterSK>
<Name>Sample Drug Name</Name>
<DrugRoutes>
<DrugRoute>
<SK>202</SK>
<Name>Intravenous</Name>
</DrugRoute>
<DrugRoute>
<SK>203</SK>
<Name>Oral</Name>
</DrugRoute>
<DrugRoute>
<SK>0</SK>
<Name>New Route</Name>
</DrugRoute>
</DrugRoutes>
<Flavor>Watermelon</Flavor>
</Drug>
结果(由于某种原因,它失去了格式,显然基于我所做的事情):
??<?xml version="1.0" encoding="utf-8"?>
<Drug xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><NewSK>NULL</NewSK><MasterSK>0</MasterSK><Name>Sample Drug Name</Name><DrugRoutes><DrugRoute><S
K>202</SK><Name>Intravenous</Name></DrugRoute><DrugRoute><SK>203</SK><Name>Oral</Name></DrugRoute><DrugRoute><NewSK>NULL</NewSK><Name>New Route</Name></DrugRoute></DrugRoutes><Flavor>Watermelon</Flavo
r></Drug>
答案 0 :(得分:2)
因此,如果我理解正确,如果名称以“SK”结尾的元素的值为0,则您希望用新值替换其内容。那是对的吗?如果是这样,这样就可以了:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[. = '0']
[substring(name(), string-length(name()) -1) = 'SK']">
<xsl:copy>
<xsl:text>This used to be 0</xsl:text>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在样本输入上运行时,结果为:
<Drug xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SK>This used to be 0</SK>
<MasterSK>This used to be 0</MasterSK>
<Name>Sample Drug Name</Name>
<DrugRoutes>
<DrugRoute>
<SK>202</SK>
<Name>Intravenous</Name>
</DrugRoute>
<DrugRoute>
<SK>203</SK>
<Name>Oral</Name>
</DrugRoute>
<DrugRoute>
<SK>This used to be 0</SK>
<Name>New Route</Name>
</DrugRoute>
</DrugRoutes>
<Flavor>Watermelon</Flavor>
</Drug>
看起来你在尝试更改元素名称时正在做一些hacky东西,但如果你想用新名称替换元素,你可以这样做:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[. = '0']
[substring(name(), string-length(name()) -1) = 'SK']">
<xsl:element name="New{name()}">
<xsl:text>This used to be 0</xsl:text>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这导致:
<Drug xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<NewSK>This used to be 0</NewSK>
<NewMasterSK>This used to be 0</NewMasterSK>
<Name>Sample Drug Name</Name>
<DrugRoutes>
<DrugRoute>
<SK>202</SK>
<Name>Intravenous</Name>
</DrugRoute>
<DrugRoute>
<SK>203</SK>
<Name>Oral</Name>
</DrugRoute>
<DrugRoute>
<NewSK>This used to be 0</NewSK>
<Name>New Route</Name>
</DrugRoute>
</DrugRoutes>
<Flavor>Watermelon</Flavor>
</Drug>