我花了相当多的时间试图弄清楚这一点,但失败并没有提供任何关于哪里出了问题的线索。我正在为一个项目尝试 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;
}
}
}
}
}
更新:感谢回复,我得到了部分工作。谁能明白为什么它在所有元素上都不匹配?正如你所看到的,它只匹配其中的两个元素,即使那样我也看不出它为什么选择这些元素的模式,而不是其他元素。
输入 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>