重命名XML节点并使用XSL替换值

时间:2014-01-09 17:29:07

标签: xml c#-4.0 xslt

我遇到的问题是什么都没有被替换。

我查看了rename nodesreplace values的其他SO问题,并复制了答案中的示例,但没有任何内容对我有用。我怀疑我有一些巧妙的错误,但我已经审查了我的C#,XML和XSL代码,似乎无法找到它。

这是我的C#代码:

private static string GetOutput(string xmlFileName, string xslFileName)
{
    var xmlDocument = new XmlDocument();
    xmlDocument.Load(xmlFileName);

    var xslTransform = new XslCompiledTransform();
    xslTransform.Load(xslFileName);

    var stream = new MemoryStream();
    xslTransform.Transform(xmlDocument, null, stream);

    stream.Position = 1;
    var reader = new StreamReader(stream);
    string output = reader.ReadToEnd();

    return output;
}

这是我的XML文件的内容:

<?xml version="1.0" encoding="utf-8" ?>
<TransformThis xmlns="http://schemas.datacontract.org/2004/07/TransformTest" 
             xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <f_name>John</f_name>
    <l_name>D&apos;Oh!</l_name>
    <Version>1.0</Version>
</TransformThis>

这是我的XSL文件的内容:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                exclude-result-prefixes="msxsl">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Version/text()[.='1.0']">1.1</xsl:template>

    <xsl:template match="f_name">
        <FirstName>
            <xsl:apply-templates select="node()|@*"/>
        </FirstName>
    </xsl:template>

    <xsl:template match="l_name">
        <LastName>
            <xsl:apply-templates select="node()|@*"/>
        </LastName>
    </xsl:template>

</xsl:stylesheet>

当我运行程序时,输出与原始XML相同。 f_name和l_name节点均未重命名,Version节点值也未被替换。

非常感谢任何帮助。

更新根据下面的michael.hor257k的答案,我修改了我的XLS文件,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:tx="http://schemas.datacontract.org/2004/07/TransformTest"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                exclude-result-prefixes="msxsl">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="tx:Version/text()[.='1.0']">1.1</xsl:template>

    <xsl:template match="tx:f_name">
        <FirstName>
            <xsl:apply-templates select="node()|@*"/>
        </FirstName>
    </xsl:template>

    <xsl:template match="tx:l_name">
        <LastName>
            <xsl:apply-templates select="node()|@*"/>
        </LastName>
    </xsl:template>

</xsl:stylesheet>

我将 ... TransformTest 命名空间添加到XLS文件中,并使用 tx:match节点添加前缀。

现在转换 正在运行,但它也将tx:namespace添加到重命名的节点:

<?xml version="1.0" encoding="utf-8"?>
<Transformer xmlns="http://schemas.datacontract.org/2004/07/TransformTest" 
             xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <FirstName xmlns="" xmlns:tx="http://schemas.datacontract.org/2004/07/TransformTest">John</FirstName>
    <LastName xmlns="" xmlns:tx="http://schemas.datacontract.org/2004/07/TransformTest">Doh</LastName>
    <Version>1.1</Version>
</Transformer>

此外,当XML被反序列化为对象时,LastName和FirstName属性为null,我怀疑这些属性与这些节点上的其他命名空间属性有关。

我希望输出看起来就像原始XML一样,但只更改了名称和值。

更新#2 michael.hor257k ADDED:他答案中的示例XLS文件。这解决了我的所有问题。

1 个答案:

答案 0 :(得分:1)

  

f_name和l_name节点都没有被重命名,也没有   版本节点值已被替换。

这些元素是<TransformThis>元素的子元素,它具有自己的命名空间。您必须在样式表中声明此命名空间,为其指定前缀,并在寻址元素或其后代时使用前缀。


<强>增加:
试试这种方式?请注意,这有点棘手,因为您实际上是将新子项添加到现有(复制)父项。这些新元素不会自动继承其养父的名称空间,并且需要明确地将它们分配给它们。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.datacontract.org/2004/07/TransformTest"
exclude-result-prefixes="ns">

<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="ns:Version/text()[.='1.0']">1.1</xsl:template>

<xsl:template match="ns:f_name">
    <xsl:element name="FirstName" namespace="http://schemas.datacontract.org/2004/07/TransformTest">
        <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
</xsl:template>

<xsl:template match="ns:l_name">
    <xsl:element name="LastName" namespace="http://schemas.datacontract.org/2004/07/TransformTest">
        <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>