【问题标题】:C# XSL Transformation Breaks EncodingC# XSL 转换中断编码
【发布时间】:2017-01-29 02:28:30
【问题描述】:

已解决 长话短说,不要在 XSL 转换中使用 CDATA。请继续阅读以了解详细信息。

背景 标准 C# 应用程序使用 XmlSerializer 将对象保存到 XML 文件。我需要获取保存的 XML 文件,添加对 XSL 转换的引用,应用所述转换,然后另存为 .graphml

问题 目前我的输出似乎有不正确的编码。 符号表示为“&lt”和“&gt”,这不是有效的 graphml(或 xml)

详情 以下是当前输出文件的样子:

<?xml version="1.0" encoding="utf-8"?>

&lt;graphml xmlns="http://graphml.graphdrawing.org/xmlns"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
 http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"&gt;

&lt;graph id="G" edgedefault="undirected"&gt;

        &lt;node id="n1"/&gt;

            &lt;edge source="n1" target="n2"/&gt;

            &lt;edge source="n1" target="n3"/&gt;

            &lt;edge source="n1" target="n5"/&gt;

            &lt;edge source="n1" target="n7"/&gt;

            &lt;edge source="n1" target="n9"/&gt;

        &lt;node id="n2"/&gt;

            &lt;edge source="n2" target="n1"/&gt;

            &lt;edge source="n2" target="n9"/&gt;

对于它的价值,我知道我正在转换的 XML 是有效的(并且格式正确),并且我知道 xsl 文件是有效的并且可以正常工作,因为我可以在其他文件上使用它就好了. C# 应用 XSL 转换的方式导致了这个问题。 以下是相关代码:

// Create an XML writer
        XmlSerializer writer = new XmlSerializer(typeof(formattedMeshNet));

        var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\netTransform.xml";
        var transformPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\GraphFormatTransform.xsl";
        var savePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ExportedNetwork.graphml";

        System.IO.FileStream file = System.IO.File.Create(path);

        writer.Serialize(file, saveMe);
        file.Close();

        // Add style sheet association
        XmlDocument xDoc = new XmlDocument();
        var transformAssn = xDoc.CreateProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"GraphFormatTransform.xsl\"");
        xDoc.AppendChild(transformAssn);


        // Load xml just saved
        System.Xml.Xsl.XslCompiledTransform myXslTransform;

        myXslTransform = new System.Xml.Xsl.XslCompiledTransform();

        myXslTransform.Load(transformPath);
        myXslTransform.Transform(path, savePath);

任何想法将不胜感激!如果您发现我遗漏了任何内容,请随时询问详细信息:)

可能相关的问题并没有真正告诉我任何事情,但您可能会得到一些有用的信息: XSL transformation give me wrong encoding

我也尝试过这里的建议: The XslCompiledTransform output encoding

谢谢!

** 编辑 **

根据请求,这里是完整的 XML 文档和相关的 XSL 转换

    <?xml version="1.0"?>
<formattedMeshNet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <contents>
    <node>
      <nodeID>1</nodeID>
      <physNeighbors>
        <int>4</int>
        <int>6</int>
        <int>7</int>
        <int>8</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>2</nodeID>
      <physNeighbors>
        <int>4</int>
        <int>11</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>3</nodeID>
      <physNeighbors>
        <int>4</int>
        <int>9</int>
        <int>10</int>
        <int>11</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>4</nodeID>
      <physNeighbors>
        <int>1</int>
        <int>2</int>
        <int>3</int>
        <int>8</int>
        <int>11</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>5</nodeID>
      <physNeighbors>
        <int>8</int>
        <int>11</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>6</nodeID>
      <physNeighbors>
        <int>1</int>
        <int>7</int>
        <int>8</int>
        <int>10</int>
        <int>12</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>7</nodeID>
      <physNeighbors>
        <int>1</int>
        <int>6</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>8</nodeID>
      <physNeighbors>
        <int>1</int>
        <int>4</int>
        <int>5</int>
        <int>6</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>9</nodeID>
      <physNeighbors>
        <int>3</int>
        <int>11</int>
        <int>12</int>
        <int>13</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>10</nodeID>
      <physNeighbors>
        <int>3</int>
        <int>6</int>
        <int>13</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>11</nodeID>
      <physNeighbors>
        <int>2</int>
        <int>3</int>
        <int>4</int>
        <int>5</int>
        <int>9</int>
        <int>13</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>12</nodeID>
      <physNeighbors>
        <int>6</int>
        <int>9</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
    <node>
      <nodeID>13</nodeID>
      <physNeighbors>
        <int>9</int>
        <int>10</int>
        <int>11</int>
      </physNeighbors>
      <visited />
      <neighbors />
    </node>
  </contents>
</formattedMeshNet>


XSL
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
    <![CDATA[
    <graphml xmlns="http://graphml.graphdrawing.org/xmlns"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
     http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">]]>

    <![CDATA[<graph id="G" edgedefault="undirected">]]>
        <xsl:for-each select="/formattedMeshNet/contents/node">
        <xsl:variable name="parentNodeID"> 
            <xsl:value-of select="nodeID" /> 
        </xsl:variable>
            <![CDATA[<node id="n]]><xsl:copy-of select="$parentNodeID" /><![CDATA["/>]]>
            <xsl:for-each select="physNeighbors/int">
                <![CDATA[<edge source="n]]><xsl:copy-of select="$parentNodeID" /><![CDATA[" target="n]]><xsl:value-of select="." /><![CDATA["/>]]>
            </xsl:for-each>
        </xsl:for-each>


    <![CDATA[</graph>
     </graphml>]]>
</xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 除了注释// Add style sheet association 之后的三行似乎没有使用和创建在其余代码中使用的任何对象外,我在 C# 中没有看到任何错误。但是XslCompiledTransformLoad和Transform的使用无论如何都没有关系,似乎没问题。所以我们需要查看最少的 XML 输入和 XSLT 样式表来判断问题所在。
  • @Martin_Honnen 我已经添加了 XML 和 XSLT 样式表
  • 您正在使用 CDATA,所以这是预期的输出。
  • @michael.hor257k 需要 CDATA 以防止我插入的标签干扰 XSL。不过,我敢打赌,您一定会有所收获,因此,如果您愿意解释如何绕过它,那将很有用。
  • 恐怕我无法解释,因为我不知道您要在这里完成什么。而且我不明白您所说的“保持插入的标签不会干扰 XSL”是什么意思。我刚刚运行了您的代码并收到了与您报告的结果相同的结果。我很确定如果你希望你的结果是 XML(就像 GraphML 应该是),那么你不应该(也不需要)在你的样式表中使用 CDATA。

标签: c# xml xslt


【解决方案1】:

如果我猜对了,你的样式表应该是这样的:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/formattedMeshNet">
    <graphml xmlns="http://graphml.graphdrawing.org/xmlns"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
     http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
        <graph id="G" edgedefault="undirected">
            <xsl:for-each select="contents/node">
                <xsl:variable name="parentNodeID" select="nodeID" /> 
                <node id="n{$parentNodeID}" />
                <xsl:for-each select="physNeighbors/int">
                    <edge source="n{$parentNodeID}" target="n{.}" />
                </xsl:for-each>
            </xsl:for-each>
        </graph>
     </graphml>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns      http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
   <graph id="G" edgedefault="undirected">
      <node id="n1"/>
      <edge source="n1" target="n4"/>
      <edge source="n1" target="n6"/>
      <edge source="n1" target="n7"/>
      <edge source="n1" target="n8"/>
      <node id="n2"/>
      <edge source="n2" target="n4"/>
      <edge source="n2" target="n11"/>
      <node id="n3"/>
      <edge source="n3" target="n4"/>
      <edge source="n3" target="n9"/>
      <edge source="n3" target="n10"/>
      <edge source="n3" target="n11"/>
      <node id="n4"/>
      <edge source="n4" target="n1"/>
      <edge source="n4" target="n2"/>
      <edge source="n4" target="n3"/>
      <edge source="n4" target="n8"/>
      <edge source="n4" target="n11"/>
      <node id="n5"/>
      <edge source="n5" target="n8"/>
      <edge source="n5" target="n11"/>
      <node id="n6"/>
      <edge source="n6" target="n1"/>
      <edge source="n6" target="n7"/>
      <edge source="n6" target="n8"/>
      <edge source="n6" target="n10"/>
      <edge source="n6" target="n12"/>
      <node id="n7"/>
      <edge source="n7" target="n1"/>
      <edge source="n7" target="n6"/>
      <node id="n8"/>
      <edge source="n8" target="n1"/>
      <edge source="n8" target="n4"/>
      <edge source="n8" target="n5"/>
      <edge source="n8" target="n6"/>
      <node id="n9"/>
      <edge source="n9" target="n3"/>
      <edge source="n9" target="n11"/>
      <edge source="n9" target="n12"/>
      <edge source="n9" target="n13"/>
      <node id="n10"/>
      <edge source="n10" target="n3"/>
      <edge source="n10" target="n6"/>
      <edge source="n10" target="n13"/>
      <node id="n11"/>
      <edge source="n11" target="n2"/>
      <edge source="n11" target="n3"/>
      <edge source="n11" target="n4"/>
      <edge source="n11" target="n5"/>
      <edge source="n11" target="n9"/>
      <edge source="n11" target="n13"/>
      <node id="n12"/>
      <edge source="n12" target="n6"/>
      <edge source="n12" target="n9"/>
      <node id="n13"/>
      <edge source="n13" target="n9"/>
      <edge source="n13" target="n10"/>
      <edge source="n13" target="n11"/>
   </graph>
</graphml>

【讨论】:

  • 成功了。我不知道 CDATA 在这种情况下不起作用。我想我假设因为我在其中包装的数据包含 XML 标记,如果我不将它放在某种包装器中,它会感到困惑。这真的要简单得多。谢谢!
  • 它不会混淆,因为样式表指令以 xsl: 为前缀,并且该前缀绑定到 XSLT 命名空间。这允许处理器区分指令和文字结果元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 2013-09-01
相关资源
最近更新 更多