2

我有以下 XML:

<?xml version="1.0" encoding="utf-8"?>
<string>
&lt;Table&gt;
&lt;Rows&gt;
&lt;Row Id="0"&gt;
&lt;Column Name="INS_NAME" XPath="Ins.Name"&gt;Jane&lt;/Column&gt;
&lt;Column Name="INS_LASTNAME" XPath="Ins.LastName"&gt;Smith&lt;/Column&gt;
&lt;/Row&gt;
&lt;Row Id="1"&gt;
&lt;Column Name="INS_NAME" XPath="Ins.Name"&gt;Joe&lt;/Column&gt;
&lt;Column Name="INS_LASTNAME" XPath="Ins.LastName"&gt;Miller&lt;/Column&gt;
&lt;/Row&gt;
&lt;Row Id="2"&gt;
&lt;Column Name="INS_NAME" XPath="Ins.Name"&gt;George&lt;/Column&gt;
&lt;Column Name="INS_LASTNAME" XPath="Ins.LastName"&gt;Ramsey&lt;/Column&gt;
&lt;/Row&gt;
&lt;/Rows&gt;
&lt;/Table&gt;
</string>

我想用一个 XSLT 把它转换成这个XML

<?xml version="1.0" encoding="utf-8"?>
<Customers>
  <Customer><Name>Jane</Name><LastName>Smith</LastName></Customer>
  <Customer><Name>Joe</Name><LastName>Miller</LastName></Customer>
  <Customer><Name>George</Name><LastName>Ramsey</LastName></Customer>
</Customers>

我可以用两个不同的 XSLT 来做到这一点:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:value-of select="/" disable-output-escaping="yes" />
  </xsl:template>
</xsl:stylesheet>

进而:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <Customers>
      <xsl:for-each select="Table/Rows/Row">
      <Customer>
        <Name><xsl:value-of select="Column[@Name='INS_NAME']" /></Name>
        <LastName><xsl:value-of select="Column[@Name='INS_LASTNAME']" /></LastName>
      </Customer>
      </xsl:for-each>
    </Customers>
  </xsl:template>
</xsl:stylesheet>

我一直在阅读有关多相变换的信息,但似乎无法理解。我尝试将第一个 XSLT 保存在变量中,但disable-output-escaping="yes"保存到变量时似乎不起作用。

有人可以帮忙吗?

谢谢你。

新信息(编辑)

我现在以这种方式翻译字符串:

<xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:variable name="stringXml">
      &lt;?xml version="1.0" encoding="utf-8"?&gt;
      <xsl:value-of select="translate(translate(/,'&gt;','&gt;'),'&lt;','&lt;')" />
    </xsl:variable>
...

如何对存储在 stringXML 中的结果 XML 进行转换?

最终解决方案(编辑)

<msxml:script implements-prefix="myLib" language="C#">
<msxml:assembly name="System.Web"/>
<msxml:using namespace="System.Web"/>
<![CDATA[
public System.Xml.XPath.XPathNodeIterator convertText(string text)
{
XmlDocument doc = new XmlDocument();
      doc.PreserveWhitespace = true;
      doc.LoadXml(text);
      return doc.CreateNavigator().Select("/");
}
]]>
</msxml:script>
4

2 回答 2

2

保存到变量时,似乎 disable-output-escaping="yes" 不起作用。

你的观察是正确的。

DOE 仅影响转换的(最终)结果的序列化,不适用于中间树

以下是W3C XSLT 1.0 规范明确规定的内容:

" XSLT 处理器只有在控制结果树的输出方式时才能禁用输出转义。情况可能并非总是如此。例如,结果树可能用作另一个 XSLT 转换的源树,而不是输出。”

对于尝试使用一个变量,它的值是一个字符串,包含 XML 文档的文本表示,同样的否定答案也成立。

于 2012-08-10T12:28:50.597 回答
1

我有类似的情况,我需要在我的实际 XML 中解析一个转义的 XML。我将发布我的解决方案以帮助其他人。另请注意,我也在使用 Saxon-PE 解析器。

在我的情况下,我的原始 XML 在子节点中包含转义的 XML。我需要在转义 XML的RootNode中获取内部XML。

源 XML:

<?xml version="1.0" encoding="utf-8"?>
<MyTestXml>
    <SomeXmlStuff>
        <Text1>Hello</Text1>
        <Text2>World</Text2>
    </SomeXmlStuff>
    <SomeEscapedXml>&lt;RootNode&gt;&lt;FirstNode&gt;Hello&lt;/FirstNode&gt;&lt;SecondNode&gt;World&lt;/SecondNode&gt;&lt;ThirdNode&gt;Again&lt;/ThirdNode&gt;&lt;/RootNode&gt;</SomeEscapedXml>
</MyTestXml>

当您取消转义 XML 时,它看起来像这样:

<RootNode>
    <FirstNode>Hello</FirstNode>
    <SecondNode>World</SecondNode>
    <ThirdNode>Again</ThirdNode>
</RootNode>

在源 XML 上应用以下 XSLT 转换:

<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet version="3.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:saxon="http://saxon.sf.net/"

                exclude-result-prefixes="xsl saxon">

    <xsl:template match="/">
        <MyOutput>      
            <xsl:call-template name="GetRootNodeInnerXml">
                <xsl:with-param name="escapedXml" select="MyTestXml/SomeEscapedXml" />
            </xsl:call-template>
        </MyOutput>
    </xsl:template>

    <xsl:template name="GetRootNodeInnerXml">
        <xsl:param name="escapedXml" required="yes" />

        <xsl:copy-of select="saxon:parse($escapedXml)/RootNode/node()"/>

        <!--  You can also use this line below if you're not using saxon parser.  Just make sure your parser supports XSL 3.0  -->
        <!--
        <xsl:copy-of select="fn:parse-xml($escapedXml)/RootNode/node()" xmlns:fn="http://www.w3.org/2005/xpath-functions"/>
        -->
    </xsl:template>
</xsl:stylesheet>

这将为您提供以下输出:

<?xml version='1.0' ?>
<MyOutput>
    <FirstNode>Hello</FirstNode>
    <SecondNode>World</SecondNode>
    <ThirdNode>Again</ThirdNode>
</MyOutput>
于 2015-09-12T23:26:41.177 回答