可能重复:
XSLT for replace attribute in XML element if it exists in another XML?
我有两个XML:
第一个XML:
<FirstXML>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
</FirstXML>
第二个XML:
<SecondXML>
<catalog>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
</SecondXML>
我想使用XSLT转换我的第一个XML。第一个xml的cd节点应替换为第二个xml的cd节点。
XSLT转换产生的XML:
<FirstXML>
<catalog>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
</FirstXML>
请为此帮助我使用XSLT。我想我们需要将Second XML作为参数传递给XSLT,我试图这样做。我是XSLT的新手,所以可能无法正确编码。 关于我们如何做到这一点的任何意见都会有所帮助。在此先感谢。
答案 0 :(得分:6)
我认为我们需要将Second XML作为参数传递给 XSLT。
这是可能的,但根本不是必需的。
更方便的方法是将文件路径传递给文档,并使用XSLT document()
函数进行解析和访问:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pDocLink" select=
"'file:///c:/temp/delete/SecondXml.xml'"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="document($pDocLink)/*/*[1]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在提供的“第一个”文档上应用此转换时:
<FirstXML>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
</FirstXML>
,“第二个”文档位于:c:\temp\delete\SecondXml.xml
:
<SecondXML>
<catalog>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
</SecondXML>
产生了想要的正确结果:
<FirstXML>
<catalog>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
</FirstXML>
答案 1 :(得分:1)
有一个document
函数,用它来处理几个输入源。
您的问题描述太模糊,无法提出更详细的建议。尝试搜索一些教程,例如http://www.ibm.com/developerworks/xml/library/x-tipcombxslt/
答案 2 :(得分:1)
您应该查看document()
功能。将XML树作为参数传递的是一些XML系统,而不是其他系统。
如果你有一个变量,如
<xsl:variable name="source" select="document('filename.xml')//catalog"/>
然后访问变量$source
将为您提供CD分支的根
修改强>
为了清楚我对Dimitre Novatchev的回答,正如我所说,你可以做到这一点,虽然你有90%的时间想要使用文档功能,但是可以将节点片段传递给样式表。来自具有AddParam的C#应用程序,并且可以在从您自己的应用程序生成数据时使用,并且不需要编写它(或者它不适用的地方)。
对于样式表,例如:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.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:param name="bonnie_tyler"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cd[ancestor::FirstXML]">
<xsl:copy>
<xsl:apply-templates select="msxsl:node-set($bonnie_tyler)//cd/*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
根据您的原始问题,您可以使用传递节点,如:
try
{
XslCompiledTransform xt = new XslCompiledTransform();
Assembly ass = Assembly.GetEntryAssembly();
Stream strm = ass.GetManifestResourceStream("ConsoleApplication1.testparam.xslt");
XmlTextReader xmr = new XmlTextReader(strm);
xt.Load(xmr);
xmr.Close();
XmlDocument originalDocument = new XmlDocument();
strm = ass.GetManifestResourceStream("ConsoleApplication1.FirstXML.xml");
originalDocument.Load(strm);
XmlDocument replacementNode = new XmlDocument();
strm = ass.GetManifestResourceStream("ConsoleApplication1.SecondXML.xml");
replacementNode.Load(strm);
XsltArgumentList arg = new XsltArgumentList();
arg.AddParam("bonnie_tyler", "", replacementNode);
StringBuilder htmlOutput = new StringBuilder();
XmlWriter writer = XmlWriter.Create(htmlOutput);
xt.Transform(originalDocument, arg, writer);
Console.Out.Write(htmlOutput.ToString());
}
它会为您提供所需的输出(尽管显然您不会像这里那样从磁盘加载文件)