1

私が解決しようとしている現在の問題は、xslt を介して相違点と類似点を持つ 2 つの 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>

2番目のファイルは次のようになります

<?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>

2 番目のファイルを 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();
        }

埋め込まれたxmlを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 の次のスニペットにヒットすると、変換は発生しません。

<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>

どんな助けや提案も大歓迎です。

4

1 に答える 1

4

問題はこのコードにあります:

  <xsl:param name="vrtfDoc2" />    

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

これは、XSLT スタイルシートを含むファイルを解析し、グローバルを見つけます。xsl:param文字列値を持つname属性を持ち"vrtfDoc2"、この子要素を選択しますが、子xsl:paramがないため、の値$vDoc2は空のノードセットです。

解決策:

ちょうど使用

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

命名上の注意

現在の名前は紛らわしく誤解を招くため、パラメーターの名前を変更してください。

  1. pパラメータには で始まる名前を使用しv、変数には で始まる名前を使用します。

  2. vrtfDoc2通常のような名前は、この変数には RTF が含まれていることを意味します (通常、そこから通常のツリーを生成するには、xxx:node-set() 関数を適用する必要があります)。ただし、これはあなたの場合には当てはまりません。

したがって、次のようなパラメータ名pDoc2はより正確で有益です。

于 2012-05-01T02:28:15.870 に答える