XSL Conversion XML-> XML выводит только текст? - PullRequest
1 голос
/ 10 мая 2009

Привет, у меня следующий код XAML, который выводится из 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>

Я хочу преобразовать его в более простой XML со следующим 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>

Я хочу, чтобы вывод имел следующий формат:

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

Но проблема в том, что все, что я получаю от этого:

  x
  1

2







  x
  3

4

Можно видеть, что есть только текст, нет текста, также фильтр не работает, x - это метка кнопки закрытия, которую я не хочу выводить.

Это код, который Iam использует для выполнения преобразования:

    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));
    }

Ответы [ 2 ]

3 голосов
/ 10 мая 2009

В XPath / XSLT 1.0, чтобы выбрать (или сопоставить) элемент, который находится в пространстве имен, вы должны объявить префикс пространства имен и использовать этот префикс в своих выражениях (или шаблонах). Не обманывайтесь тем фактом, что <StackPanel> и другие элементы не используют префиксы во входном XML. Он использует пространство имен по умолчанию, как определено в объявлении пространства имен по умолчанию:

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

Таким образом, вам нужно соответствующее объявление в вашей таблице стилей (как вы сделали для пространства имен "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" в моем примере выше):

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

Причина, по которой вы видите вывод, в том, что ваше шаблонное правило никогда не вызывается (потому что имя не совпадает). Вместо этого вызывается встроенный шаблон правил для каждого из типов узлов XPath. Корневой узел и узлы элемента должны просто обрабатывать дочерние элементы. Для текстовых узлов это копировать их через. Таким образом, поведение, которое вы видите, такое же, как и при работе с любой пустой таблицей стилей (в которой нет шаблонных правил): дамп всех текстовых узлов во входном документе.

Может быть больно иметь префикс каждого теста имени в каждом выражении или шаблоне. Вот почему в XSLT 2.0 появилась функция под названием xpath-default-namespace, которая позволяет выражениям XPath и шаблонам XSLT использовать пространство имен по умолчанию, как это делают элементы в XML. В этом случае все, что вам нужно изменить, это добавить одну строку:

<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.)

Прежде чем покинуть вас, я вижу еще несколько проблем в вашей таблице стилей (которые вы, без сомнения, обнаружите дальше):

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

Начало выражения с «/» означает «начать с документа / корневого узла». Таким образом, эти выражения ищут элемент документа <tagsTextBox> и элемент документа <contentTextBox> соответственно. Исходя из того, что я вижу в вашем образце входного документа, я думаю, что вы хотели написать так:

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

Надеюсь, это поможет! Дайте мне знать, если что-то потребует дальнейшего объяснения.

1 голос
/ 10 мая 2009

Вы проблемы в XSLT, по крайней мере:

  1. Вам необходимо поместить соответствующие выражения в правильные пространства имен, чтобы они соответствовали. Э.Г.

    ... xml:xaml='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
    <xsl:template match='/xaml:StackPanel'>...
    
  2. Выражения value-of (соответствуют /tagsTextBox и /contentText) Boxseem должны соответствовать в StackPanel, но:

    • Также отсутствует квалификация пространства имен
    • Соответствует непосредственным дочерним элементам корня документа, а не дочерним узлам текущего узла содержимого. Скорее всего вам нужно:

      <xsl:value-of select='descendent::xaml:TextBox'/>
      

И, возможно, больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...