XSL 转换 XML->XML 只输出文本? [英] XSL Conversion XML->XML outputs only text?

查看:28
本文介绍了XSL 转换 XML->XML 只输出文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 XAML 代码,它是 XamlWriter.Save() 的输出:

Hi I have following XAML code which is the output from XamlWriter.Save():

<StackPanel Name="itemStack" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mm="clr-namespace:MindManager;assembly=MindManager">
  <mm:Item Width="Auto" Height="Auto">
    <Border BorderThickness="10,10,10,10" Name="border1" Height="Auto">
      <DockPanel>
        <DockPanel LastChildFill="True" Name="dockPanel1" Height="33" DockPanel.Dock="Top">
          <Button Name="deleteItemButton" Width="26" Height="21.638" FlowDirection="LeftToRight" DockPanel.Dock="Right" Grid.IsSharedSizeScope="False">x</Button>
          <TextBox Name="tagsTextBox" Height="19">1</TextBox>
        </DockPanel>
        <TextBox TextWrapping="Wrap" MinLines="5" AcceptsReturn="True" AcceptsTab="True" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled" AutoWordSelection="True" Name="contentTextBox" Width="Auto" MinWidth="600" Height="Auto" MinHeight="80">2</TextBox>
      </DockPanel>
    </Border>
  </mm:Item>
  <mm:Item Width="Auto" Height="Auto">
    <Border BorderThickness="10,10,10,10" Name="border1" Height="Auto">
      <DockPanel>
        <DockPanel LastChildFill="True" Name="dockPanel1" Height="33" DockPanel.Dock="Top">
          <Button Name="deleteItemButton" Width="26" Height="21.638" FlowDirection="LeftToRight" DockPanel.Dock="Right" Grid.IsSharedSizeScope="False">x</Button>
          <TextBox Name="tagsTextBox" Height="19">3</TextBox>
        </DockPanel>
        <TextBox TextWrapping="Wrap" MinLines="5" AcceptsReturn="True" AcceptsTab="True" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled" AutoWordSelection="True" Name="contentTextBox" Width="Auto" MinWidth="600" Height="Auto" MinHeight="80">4</TextBox>
      </DockPanel>
    </Border>
  </mm:Item>
</StackPanel>

我想使用以下 XSL 将其转换为更简单的 XML:

I want to convert it to simpler XML with the following 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" xmlns:mm="clr-namespace:MindManager;assembly=MindManager">  
  <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/StackPanel">
      <mindcontainer>
        <xsl:for-each select="mm:Item">
          <minditem>
            <xsl:value-of select="/tagsTextBox"/>
            <xsl:value-of select="/contentTextBox"/>
          </minditem>
        </xsl:for-each>
      </mindcontainer>
    </xsl:template>
</xsl:stylesheet>

我希望输出具有以下格式:

I want the output to have the following format:

<mindcontainer>
 <minditem>
   content of tagsTextBox
   content of contentTextBox
 </minditem>
 <minditem>
   content of tagsTextBox
   content of contentTextBox
 </minditem>
</mindcontainer>

但问题是我从中得到的只是:

But the problem is that all I get from it is:

  x
  1

2







  x
  3

4

可以看到只有文本,没有文本,过滤器也不起作用 x 是我不想输出的关闭按钮的标签.

One can see that there is only text, there are not text, also the filter doesn't work the x is the label of the close button which I do not want to be outputted.

这是我用来执行转换的代码:

This is the code Iam using to perform the transform:

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent=true;

    StringBuilder sb = new StringBuilder();
    using (XmlWriter wr = XmlWriter.Create(sb, settings))
    {
        XamlWriter.Save(scrollViewer1.Content, wr);
    }

    settings.ConformanceLevel = ConformanceLevel.Auto;
    using (XmlReader rd = XmlReader.Create(new StringReader(sb.ToString())))
    {
        XslCompiledTransform trans = new XslCompiledTransform();
        trans.Load("output.xsl");

        trans.Transform(rd, XmlWriter.Create("mindstore.xms", settings));
    }

推荐答案

在 XPath/XSLT 1.0 中,要选择(或匹配)位于命名空间中的元素,您必须声明命名空间前缀和在您的表达式(或模式)中使用该前缀.不要被 和其他元素在输入 XML 中不使用前缀这一事实所迷惑.它使用默认命名空间,由这个默认命名空间声明决定:

In XPath/XSLT 1.0, to select (or match) an element that's in a namespace, you must declare a namespace prefix and use that prefix in your expressions (or patterns). Don't be fooled by the fact that <StackPanel> and other elements don't use prefixes in the input XML. It's using a default namespace, as determined by this default namespace declaration:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

所以你需要在你的样式表中有一个相应的声明(就像你对mm"命名空间所做的那样),除了你需要选择一个命名空间前缀来使用.任何前缀都可以(就像您实际上不必使用mm"一样).

So you need a corresponding declaration in your stylesheet (as you did for the "mm" namespace), except that you need to pick a namespace prefix to use. Any prefix will do (just as you didn't actually have to use "mm").

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  ...>

然后,在您的样式表中,您需要更新您的表达式和模式以使用您选择的前缀(在我上面的示例中为x"):

Then, in your stylesheet, you need to update your expressions and patterns to use the prefix you chose ("x" in my example above):

<xsl:template match="/x:StackPanel">

您看到输出的原因是您的模板规则从未被调用(因为名称不匹配).相反,每个 XPath 节点类型的内置模板规则都会被调用.对于根节点和元素节点,它只是继续处理子节点.对于文本节点,就是复制它们.因此,您看到的行为与您使用任何空样式表(没有模板规则)所获得的行为相同:输入文档中所有文本节点的转储.

The reason you're seeing the output you're getting is that your template rule isn't ever getting invoked (because the name doesn't match). Instead, the built-in template rules for each of the XPath node types is getting invoked. For the root node and element nodes, it's to just keep processing children. For text nodes, it's to copy them through. Thus, the behavior you're seeing is the same behavior you'd get with any empty stylesheet (that has no template rules): a dump of all the text nodes in the input document.

必须在每个表达式或模式中为每个名称测试添加前缀可能会很痛苦.这就是 XSLT 2.0 引入名为 xpath-default-namespace 的特性的原因,它使 XPath 表达式和 XSLT 模式可以使用默认命名空间,就像 XML 中的元素一样.在这种情况下,您所要做的就是添加一行:

It can be a pain to have to prefix every name test in every expression or pattern. That's why XSLT 2.0 introduced a feature called xpath-default-namespace, which makes it possible for XPath expressions and XSLT patterns to use a default namespace, just like elements can in XML. In that case, all you'd have to change is to add one line:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xpath-default-namespace="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  ...>

但这仅在您使用 XSLT 2.0 处理器时才适用.(例如,MSXML 不支持 XSLT 2.0.)

But that's only if you you're using an XSLT 2.0 processor. (MSXML, for example, doesn't support XSLT 2.0.)

在我离开您之前,我在您的样式表中看到了更多问题(毫无疑问,您接下来会发现):

Before I leave you, I see some more issues in your stylesheet (which you, no doubt, would have discovered next):

        <xsl:value-of select="/tagsTextBox"/>
        <xsl:value-of select="/contentTextBox"/>

/"开头的表达式表示从文档/根节点开始".所以这些表达式分别寻找 文档元素和 文档元素.根据我在您的示例输入文档中看到的内容,我认为您要写的是:

Starting an expression with "/" means "start from the document/root node". So these expressions are looking for a <tagsTextBox> document element and a <contentTextBox> document element, respectively. Based on what I see in your sample input document, I think what you meant to write is this:

        <xsl:value-of select=".//x:TextBox[@Name = 'tagsTextBox']"/>
        <xsl:value-of select=".//x:TextBox[@Name = 'contentTextBox']"/>

希望这有帮助!如果需要进一步解释,请告诉我.

Hope this helps! Let me know if anything needs further explanation.

这篇关于XSL 转换 XML->XML 只输出文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆