gpt4 book ai didi

c# - 将 Xml 代码段作为参数传递到 xslt

转载 作者:太空宇宙 更新时间:2023-11-03 22:00:21 26 4
gpt4 key购买 nike

我正在尝试解决的当前问题是通过 xslt 生成两个具有异同的 xml 文件的比较。

例如第一个xml文件看起来像

<?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 文件中时,输出按预期工作:

<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# 代码时:

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 时

<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 中命中以下代码段时,不会发生转换:

<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:param name="vrtfDoc2" />    

<xsl:variable name="vDoc2" select=
"document('')/*/xsl:param[@name='vrtfDoc2']/*"/>

这会解析包含 XSLT 样式表的文件,找到 globa; xsl:param 具有字符串值为 "vrtfDoc2"name 属性,并选择此 xsl:param 的子元素> -- 但是它没有子节点,因此 $vDoc2 的值为空节点集。

解决方案:

仅使用:

<xsl:variable name="vDoc2" select="$vrtfDoc2/*"/>

命名注意事项:

请重命名该参数,因为其当前名称容易引起混淆和误导:

  1. 对参数使用以 p 开头的名称,对变量使用以 v 开头的名称。

  2. vrtfDoc2 这样的名称通常意味着:此变量包含一个 RTF(并且通常需要对其应用 xxx:node-set() 函数才能生成一棵普通的树)。但是,您的情况并非如此。

因此,像这样的参数名称:pDoc2 更加精确和信息丰富。

关于c# - 将 Xml 代码段作为参数传递到 xslt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10392292/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com