将 Xml Snippet 作为参数传递给 xslt [英] Passing Xml Snippet into xslt as parameter
问题描述
我正在尝试解决的当前问题是通过 xslt 生成两个具有差异和相似性的 xml 文件的比较.
A current problem I am trying to solve is generating a comparison of two xml files with differences and similarities via xslt.
例如第一个 xml 文件看起来像
For example the first xml file looks like
<?xml version="1.0" encoding="utf-8" ?>
<Stats Date="2011-01-01">
<Player Rank="1">
<GP>39</GP>
<G>32</G>
<A>33</A>
<PlusMinus>20</PlusMinus>
<PIM>29</PIM>
<PP>10</PP>
<SH>1</SH>
<GW>3</GW>
<Shots>0</Shots>
<ShotPctg>154</ShotPctg>
<TOIPerGame>20.8</TOIPerGame>
<ShiftsPerGame>21:54</ShiftsPerGame>
<FOWinPctg>22.6</FOWinPctg>
</Player>
</Stats>
第二个文件看起来像
<?xml version="1.0" encoding="utf-8" ?>
<Stats Date="2011-01-01">
<Player Rank="2">
<Name>John Smith</Name>
<Team>NY</Team>
<Pos>D</Pos>
<GP>38</GP>
<G>32</G>
<A>33</A>
<PlusMinus>15</PlusMinus>
<PIM>29</PIM>
<PP>10</PP>
<SH>1</SH>
<GW>4</GW>
<Shots>0</Shots>
<ShotPctg>158</ShotPctg>
<TOIPerGame>20.8</TOIPerGame>
<ShiftsPerGame>21:54</ShiftsPerGame>
<FOWinPctg>22.6</FOWinPctg>
</Player>
</Stats>
当我将第二个文件嵌入到 xslt 文件中时,输出按预期工作:
When I embed the second file into the xslt file the output works as expected:
<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="vrtfDoc2">
<Stats Date="2011-01-01">
<Player Rank="2">
<Name>John Smith</Name>
<Team>NY</Team>
<Pos>D</Pos>
<GP>38</GP>
<G>32</G>
<A>33</A>
<PlusMinus>15</PlusMinus>
<PIM>29</PIM>
<PP>10</PP>
<SH>1</SH>
<GW>4</GW>
<Shots>0</Shots>
<ShotPctg>158</ShotPctg>
<TOIPerGame>20.8</TOIPerGame>
<ShiftsPerGame>21:54</ShiftsPerGame>
<FOWinPctg>22.6</FOWinPctg>
</Player>
</Stats>
</xsl:param>
<xsl:variable name="vDoc2" select=
"document('')/*/xsl:param[@name='vrtfDoc2']/*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:param name="pDoc2"/>
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:with-param name="pDoc2" select="$pDoc2"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="*">
<xsl:with-param name="pDoc2" select="$vDoc2"/>
</xsl:apply-templates>
-----------------------
<xsl:apply-templates select="$vDoc2">
<xsl:with-param name="pDoc2" select="/*"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Player/*">
<xsl:param name="pDoc2"/>
<xsl:if test=
"not(. = $pDoc2/*/*[name()=name(current())])">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
<xsl:template match="Name|Team|Pos" priority="20"/>
</xsl:stylesheet>
使用以下 c# 代码时:
when using the following c# code:
private string Transform(string xml, string xml2, string xsl) {
StringWriter writer = new StringWriter();
XslCompiledTransform t = new XslCompiledTransform(true);
XsltSettings settings = new XsltSettings(true, false);
XmlTextReader xmlReader = new XmlTextReader(xml);
XmlTextReader xslReader = new XmlTextReader(xsl);
t.Load(xslReader, settings, null);
t.Transform(xmlReader, null, writer);
return writer.ToString();
}
当我从 xslt 中删除嵌入的 xml 时
When I remove the embedded xml from the xslt
<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="vrtfDoc2" />
<xsl:variable name="vDoc2" select=
"document('')/*/xsl:param[@name='vrtfDoc2']/*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:param name="pDoc2"/>
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:with-param name="pDoc2" select="$pDoc2"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="*">
<xsl:with-param name="pDoc2" select="$vDoc2"/>
</xsl:apply-templates>
-----------------------
<xsl:apply-templates select="$vDoc2">
<xsl:with-param name="pDoc2" select="/*"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Player/*">
<xsl:param name="pDoc2"/>
<xsl:if test=
"not(. = $pDoc2/*/*[name()=name(current())])">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
<xsl:template match="Name|Team|Pos" priority="20"/>
</xsl:stylesheet>
将c#方法改为
private string Transform(string xml, string xml2, string xsl) {
StringWriter writer = new StringWriter();
XslCompiledTransform t = new XslCompiledTransform(true);
XsltSettings settings = new XsltSettings(true, false);
XmlTextReader xmlReader = new XmlTextReader(xml);
XmlDocument doc1 = new XmlDocument();
// populate as needed e.g.
doc1.Load(xml2);
XmlTextReader xslReader = new XmlTextReader(xsl);
t.Load(xslReader, settings, null);
//Pass parameter value to xslt from code
XsltArgumentList argumentList = new XsltArgumentList();
argumentList.AddParam("vrtfDoc2", "", doc1);
t.Transform(xmlReader, argumentList, writer);
return writer.ToString();
}
我从转换中得到一个空白输出,我一生都无法理解为什么.我已经使用调试器逐步浏览了两个版本,并且参数值在两种情况下看起来都相同,但是当传递的参数版本命中 xslt 中的以下代码段时,不会发生任何转换:
I get a blank output from the transform, for the life of me I can't understand why. I've stepped through both versions using the debugger and the parameter value looks identical in both occassions but when the parameter passed version hits the following snippet in the xslt no transform occurs:
<xsl:apply-templates select="$vDoc2">
<xsl:with-param name="pDoc2" select="/*"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Player/*">
<xsl:param name="pDoc2"/>
<xsl:if test=
"not(. = $pDoc2/*/*[name()=name(current())])">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
如有任何帮助或建议,我们将不胜感激.
Any help or suggestions would be much appeciated.
推荐答案
问题出在这段代码:
<xsl:param name="vrtfDoc2" />
<xsl:variable name="vDoc2" select=
"document('')/*/xsl:param[@name='vrtfDoc2']/*"/>
这将解析包含 XSLT 样式表的文件,定位 globa;xsl:param
具有 name
属性和字符串值 "vrtfDoc2"
并选择此 xsl:param
的子元素> -- 但是它没有子节点,因此 $vDoc2
的值是空节点集.
This parses the file that contains the XSLT stylesheet, locates the globa; xsl:param
that has name
attribute with string value "vrtfDoc2"
and selects the children elements of this xsl:param
-- however it has no children, therefore the value of $vDoc2
is the empty node-set.
解决方案:
只使用:
<xsl:variable name="vDoc2" select="$vrtfDoc2/*"/>
命名注意事项:
请重命名参数,因为它的当前名称令人困惑和误导:
Please rename the parameter as its current name is confusing and misleading:
使用以
p
开头的名称作为参数,使用以v
开头的名称作为变量.
Use names starting with
p
for parameters and names starting withv
for variables.
像 vrtfDoc2
这样的名字通常意味着:这个变量包含一个 RTF(并且通常需要 xxx:node-set() 函数应用于它以产生来自它的常规树).但是,您的情况并非如此.
A name like vrtfDoc2
usually means: this variable contains an RTF (and usually needs the xxx:node-set() function to be applied to it in order to produce a regular tree from it). However, this isn't the case in your case.
因此,像这样的参数名称:pDoc2
会更精确、信息量更大.
Therefore, a parameter name like: pDoc2
is more precise and informative.
这篇关于将 Xml Snippet 作为参数传递给 xslt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!