处理编码元素

时间:2012-02-06 16:30:02

标签: c# .net xml xslt

我的xslt转换没有拿起我的文档,这是因为某些/大多数元素都是编码的,

e.g。我的文件:

<Template>
  <ID>14</ID>
  <Name>name of report</Name>
  <VersionNumber>1.0</VersionNumber>
  <CoverPage>
&lt;br /&gt;
&lt;br /&gt;
&lt;h3 style="text-align: center;"&gt;
&lt;br class="GENTICS_ephemera" /&gt;
&lt;/h3&gt;
&lt;h3 style="text-align: center;"&gt;
&lt;br class="GENTICS_ephemera" /&gt;
&lt;/h3&gt;
&lt;h3 style="text-align: center;"&gt;Property Valuation Report&lt;/h3&gt;  
  </CoverPage>
</Template>

这永远不会奏效:

  <xsl:template match="span">
    <fo:inline>
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates select="*|text()"/>
    </fo:inline>
  </xsl:template>
 <xsl:template match="br">
    <fo:block>
      <fo:leader />
    </fo:block>
  </xsl:template>

问题:如何以正确的格式获取我的文档(从技术上讲,我的xml是有效且格式正确的)但我想进行xsl转换,因此我需要能够获取正确的标记

以下是我的转换方法:

    private static MemoryStream Transform(XNode xmlData, XNode xslt)
    {
        XmlWriter writer = null;
        var xslTrans = new XslCompiledTransform();
        try
        {
            //load the xsl
            xslTrans.Load(xslt.CreateReader());

            //create the output stream
            var result = new MemoryStream();
            writer = XmlWriter.Create(result, null);

            //create the xml reader for the data
            var data = xmlData.CreateReader();

            //do the actual transform of xml
            xslTrans.Transform(data, null, writer);

            writer.Close();
            return new MemoryStream(result.ToArray());

        }
        catch (Exception e)
        {
            var errors = XslErrors.GetCompileErrors(xslTrans);
            if (errors == null)
            {
                // Failed to obtain list of compile errors
                throw;
            }

            if (writer != null) writer.Close();
            throw e;
        }
    }

更新我的XSLT文档...

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format" version="2.0"
                xmlns:fp="http://example.com/fp"
                exclude-result-prefixes="fp">

  <xsl:output method="xml" indent="yes" omit-xml-declaration="no"  />
  <xsl:variable name="pagewidth" select="21.5"/>
  <xsl:variable name="bodywidth" select="17"/>
  <xsl:template match="Template">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family="Arial" font-size="9pt" color="black">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="Cover" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
          <fo:region-body/>
        </fo:simple-page-master>

        <fo:simple-page-master master-name="BodyContent" page-height="29.7cm" page-width="21cm">
          <fo:region-body margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm"/>
          <!-- Header -->
          <fo:region-before margin-bottom="2cm" extent="5cm" padding="0cm" border-width="0cm"/>
          <!-- Footer -->
          <fo:region-after margin-top="2cm" extent="2cm" padding="0cm" border-width="0cm"/>
        </fo:simple-page-master>
      </fo:layout-master-set>

      <fo:page-sequence master-reference="Cover">
        <fo:flow flow-name="xsl-region-body" >
          <fo:block id="CoverPageWrapper">
            <xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
            <xsl:apply-templates select="CoverPage" />
          </fo:block>
        </fo:flow>
      </fo:page-sequence>

      <fo:page-sequence master-reference="BodyContent" initial-page-number="1">
        <fo:static-content flow-name="xsl-region-before">
          <fo:table margin-left="2cm" padding-top="1cm" table-layout="fixed" width="170mm">
            <fo:table-column column-width="70mm" />
            <fo:table-column column-width="100mm" />
            <fo:table-body>
              <fo:table-row>
                <fo:table-cell padding-start="1pt" padding-end="1pt" padding-before="1pt" padding-after="1pt" padding-top="1pt" padding-bottom="1pt">
                  <fo:block-container width="3cm" height="2cm">
                    <fo:block>

                    </fo:block>
                  </fo:block-container>
                </fo:table-cell>
                <fo:table-cell padding-start="1pt" padding-end="1pt" padding-before="1pt" padding-after="1pt" padding-top="1pt" padding-bottom="1pt">
                  <fo:block-container width="4cm" height="2.2cm">
                    <fo:block>

                    </fo:block>
                  </fo:block-container>
                </fo:table-cell>
              </fo:table-row>
            </fo:table-body>
          </fo:table>
        </fo:static-content>

        <fo:static-content flow-name="xsl-region-after">
          <fo:block text-align="center" font-size="8pt" padding-top="0.5cm">
            Page
            <fo:page-number/>
            of
            <fo:page-number-citation ref-id="FinalPage"/>
          </fo:block>
        </fo:static-content>

        <fo:flow flow-name="xsl-region-body">
          <fo:block id="BodyContentWrapper">
            <xsl:apply-templates select="Body" />
          </fo:block>
          <!-- End of the document stuff that is needed-->
          <fo:block id="FinalPage"/>

        </fo:flow>
      </fo:page-sequence>

    </fo:root>
  </xsl:template>

  <xsl:template match="label[@data-field-class='ui-templatefield']">
    <xsl:choose>
      <xsl:when test="@fo-checkbox" >
        <xsl:choose>
          <xsl:when test="text()='True'">
            <fo:inline font-size="9pt" color="black">
              [
              <fo:inline font-family="ZapfDingbats" border-color="black" border-style="solid" border-width="1pt" font-size="6pt">&#x2715;</fo:inline>
              ]
            </fo:inline>
          </xsl:when>
          <xsl:otherwise>
            <fo:inline>
              [&#160;&#160;&#160;]
              <!-->fo:inline font-family="ZapfDingbats" font-size="10pt">&#x274F;</fo:inline-->
            </fo:inline>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <fo:inline>
          <xsl:apply-templates select="*|text()"/>
        </fo:inline>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="span">
    <fo:inline>
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates select="*|text()"/>
    </fo:inline>
  </xsl:template>

  <xsl:template match="blockquote">
    <fo:block
      space-before="6pt" space-after="6pt"
      start-indent="1em" end-indent="1em">
      <xsl:apply-templates select="*|text()"/>
    </fo:block>
  </xsl:template>

  <xsl:template match="h1">
    <fo:block font-size="22pt">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="h2">
    <fo:block font-size="18pt">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="h3">
    <fo:block font-size="16pt">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="h4">
    <fo:block font-size="14pt">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="h5">
    <fo:block font-size="12pt" font-weight="bold">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="h6">
    <fo:block font-size="10pt" font-weight="bold">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template name="tokenize-style">
    <xsl:param name="pString" select="string(@style)"/>
    <xsl:choose>
      <xsl:when test="not($pString)"/>
      <xsl:when test="contains($pString,';')">
        <xsl:call-template name="tokenize-style">
          <xsl:with-param name="pString"
               select="substring-before($pString,';')"/>
        </xsl:call-template>
        <xsl:call-template name="tokenize-style">
          <xsl:with-param name="pString"
               select="substring-after($pString,';')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:attribute name="{normalize-space(substring-before($pString,':'))}">
          <xsl:value-of select="normalize-space(substring-after($pString,':'))"/>
        </xsl:attribute>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="div">
    <fo:block>
      <xsl:if test="@class='bordered'">
        <xsl:attribute name="border-width">1pt</xsl:attribute>
        <xsl:attribute name="border-style">solid</xsl:attribute>
      </xsl:if>
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates select="*|text()"/>
    </fo:block>
  </xsl:template>

  <xsl:template match="p" >
    <fo:block space-before="4pt" space-after="4pt">
      <xsl:call-template name="tokenize-style"/>
      <xsl:apply-templates select="*|text()"/>
    </fo:block>
  </xsl:template>

  <xsl:template match="ol">
    <fo:list-block start-indent="1cm" space-before="6pt" space-after="6pt">
      <xsl:apply-templates/>
    </fo:list-block>
  </xsl:template>

  <xsl:template match="ol/li">
    <fo:list-item>
      <fo:list-item-label end-indent="label-end()">
        <fo:block>
          <xsl:choose>
            <xsl:when test="../@type != ''">
              <xsl:number format="{../@type}"/>.
            </xsl:when>
            <xsl:otherwise>
              <xsl:number format="1"/>.
            </xsl:otherwise>
          </xsl:choose>
        </fo:block>
      </fo:list-item-label>
      <fo:list-item-body start-indent="body-start()">
        <fo:block font-size="11pt" color="black" font-family="Arial, Verdana, sans-serif">
          <xsl:apply-templates/>
        </fo:block>
      </fo:list-item-body>
    </fo:list-item>
  </xsl:template>

  <xsl:template match="ul">
    <fo:list-block start-indent="1cm" space-before="6pt" space-after="6pt">
      <xsl:apply-templates/>
    </fo:list-block>
  </xsl:template>

  <xsl:template match="ul/li">
    <fo:list-item>
      <fo:list-item-label end-indent="label-end()">
        <xsl:choose>
          <xsl:when test="../@type ='disc'">
            <fo:block>&#x2022;</fo:block>
          </xsl:when>
          <xsl:when test="../@type='square'">
            <fo:block font-family="ZapfDingbats">n</fo:block>
          </xsl:when>
          <xsl:when test="../@type='circle'">
            <fo:block font-family="ZapfDingbats">m</fo:block>
          </xsl:when>
          <xsl:otherwise>
            <xsl:choose>
              <xsl:when test="count(ancestor::ul) = 1">
                <fo:block>&#x2022;</fo:block>
              </xsl:when>
              <xsl:when test="count(ancestor::ul) = 2">
                <fo:block font-family="ZapfDingbats">m</fo:block>
              </xsl:when>
              <xsl:otherwise>
                <fo:block font-family="ZapfDingbats">n</fo:block>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:otherwise>
        </xsl:choose>
      </fo:list-item-label>
      <fo:list-item-body start-indent="body-start()">
        <fo:block>
          <xsl:apply-templates/>
        </fo:block>
      </fo:list-item-body>
    </fo:list-item>
  </xsl:template>

  <xsl:template match="dl">
    <fo:block space-before="6pt" space-after="6pt">
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="dt">
    <fo:block>
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="dd">
    <fo:block start-indent="5mm">
      <xsl:apply-templates/>
    </fo:block>
  </xsl:template>

  <xsl:template match="table">
    <fo:table>
      <xsl:attribute name="width">
        <xsl:text>170mm</xsl:text>
      </xsl:attribute>
      <xsl:apply-templates select="*|text()"/>
    </fo:table>
  </xsl:template>

  <xsl:template match="caption">
    <fo:caption>
      <fo:block>
        <xsl:apply-templates />
      </fo:block>
    </fo:caption>
  </xsl:template>

  <xsl:template match="colgroup">
    <xsl:for-each select="col">
      <fo:table-column>
        <xsl:attribute name="column-width">
          <xsl:choose>
            <xsl:when test="contains(@width, '%')">
              <xsl:value-of disable-output-escaping="yes"  select="floor(number(translate(@width,'%','')) div 100 * $bodywidth)"/>
              <xsl:text>cm</xsl:text>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of disable-output-escaping="yes" select="floor(@width div 72)"/>
              <xsl:text>in</xsl:text>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:attribute>
      </fo:table-column>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="tbody">
    <fo:table-body>
      <xsl:apply-templates select="*|text()"/>
    </fo:table-body>
  </xsl:template>

  <xsl:template match="tr">
    <fo:table-row>
      <xsl:apply-templates select="*|text()"/>
    </fo:table-row>
  </xsl:template>

  <xsl:template match="th">
    <fo:table-cell font-weight="bold" text-align="center">
      <xsl:if test="ancestor::table/@border > 0">
        <xsl:attribute name="border-style">solid</xsl:attribute>
        <xsl:attribute name="border-width">0.1mm</xsl:attribute>
      </xsl:if>
      <fo:block>
        <xsl:apply-templates select="*|text()"/>
      </fo:block>
    </fo:table-cell>
  </xsl:template>

  <xsl:template match="td">
    <fo:table-cell  padding-start="1pt" padding-end="1pt" padding-before="1pt" padding-after="1pt" padding-top="1pt" padding-bottom="1pt">
      <xsl:if test="ancestor::table/@border > 0">
        <xsl:attribute name="border-style">solid</xsl:attribute>
        <xsl:attribute name="border-width">0.1mm</xsl:attribute>
      </xsl:if>
      <xsl:if test="ancestor::tr/@class='titleformat'">
        <xsl:attribute name="background-color">black</xsl:attribute>
        <xsl:attribute name="color">white</xsl:attribute>
        <xsl:attribute name="font-size">9pt</xsl:attribute>
      </xsl:if>
      <fo:block>
        <xsl:apply-templates select="*|text()"/>
      </fo:block>
    </fo:table-cell>
  </xsl:template>

  <xsl:template match="tt">
    <fo:inline font-family="monospace">
      <xsl:apply-templates  select="*|text()"/>
    </fo:inline>
  </xsl:template>

  <xsl:template match="img">
    <fo:external-graphic>
      <xsl:attribute name="src">
        file:<xsl:value-of
        select="@src"/>
      </xsl:attribute>
      <xsl:attribute name="width">
        <xsl:value-of
        select="@width"/>px
      </xsl:attribute>
      <xsl:attribute name="height">
        <xsl:value-of
        select="@height"/>px
      </xsl:attribute>
    </fo:external-graphic>
  </xsl:template>

  <xsl:template match="pre">
    <fo:block white-space-collapse="false">
      <xsl:apply-templates select="*|text()"/>
    </fo:block>
  </xsl:template>

  <xsl:template match="b">
    <fo:inline>
      <xsl:attribute name="font-weight">bold</xsl:attribute>
      <xsl:apply-templates select="*|text()"/>
    </fo:inline>
  </xsl:template>

  <xsl:template match="i">
    <fo:inline>
      <xsl:attribute name="font-style">italic</xsl:attribute>
      <xsl:apply-templates select="*|text()"/>
    </fo:inline>
  </xsl:template>

  <xsl:template match="hr">
    <xsl:if test="@class='ui-pagebreak'">
      <fo:block break-after="page" />
    </xsl:if>
    <xsl:if test="@class=''">
      <fo:block>
        <fo:leader
          leader-pattern="rule" leader-length.optimum="100%"
          rule-style="double" rule-thickness="1pt"/>
      </fo:block>
    </xsl:if>
  </xsl:template>

  <xsl:template match="br">
    <fo:block>
      <fo:leader />
    </fo:block>
  </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

以下是XslCompiledTransform和扩展对象的示例:

class Program
{
    static void Main(string[] args)
    {
        XslCompiledTransform proc = new XslCompiledTransform();
        proc.Load("../../XSLTFile1.xslt");

        XsltArgumentList xsltArgs = new XsltArgumentList();
        xsltArgs.AddExtensionObject("http://example.com/fp", new FragmentParser());

        proc.Transform("../../XMLFile1.xml", xsltArgs, Console.Out);
    }
}

public class FragmentParser
{
    public IXPathNavigable ParseFragment(string fragment)
    {
        XmlDocument doc = new XmlDocument();
        XmlDocumentFragment frag = doc.CreateDocumentFragment();
        frag.InnerXml = fragment;
        return frag;
    }
}

然后在样式表中,您可以使用以下代码:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fp="http://example.com/fp"
  exclude-result-prefixes="fp"
>
  <xsl:template match="CoverPage">
    <Test>
      <xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
    </Test>
  </xsl:template>

  <xsl:template match="h3">
    <heading>
      <xsl:apply-templates/>
    </heading>
  </xsl:template>
</xsl:stylesheet>

[编辑] 在样式表中,您可以更改

  <fo:page-sequence master-reference="Cover">
    <fo:flow flow-name="xsl-region-body" >
      <fo:block id="CoverPageWrapper">
        <xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
        <xsl:apply-templates select="CoverPage" />
      </fo:block>
    </fo:flow>
  </fo:page-sequence>

  <fo:page-sequence master-reference="Cover">
    <fo:flow flow-name="xsl-region-body" >
      <fo:block id="CoverPageWrapper">
        <xsl:apply-templates select="fp:ParseFragment(CoverPage)/node()"/>
      </fo:block>
    </fo:flow>
  </fo:page-sequence>

或为CoverPage添加模板,例如

<xsl:template match="CoverPage">
  <xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
</xsl:template>

然后在上面你就可以做到这一点。

  <fo:page-sequence master-reference="Cover">
    <fo:flow flow-name="xsl-region-body" >
      <fo:block id="CoverPageWrapper">
        <xsl:apply-templates select="CoverPage" />
      </fo:block>
    </fo:flow>
  </fo:page-sequence>