将 Xml Snippet 作为参数传递给 xslt [英] Passing Xml Snippet into xslt as parameter

查看:28
本文介绍了将 Xml Snippet 作为参数传递给 xslt的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解决的当前问题是通过 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:

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

  1. Use names starting with p for parameters and names starting with v 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆