1

次のようなXML(XAML)文字列があります。

<Zot xmlns="clr-namespace:A.B;assembly=A"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Zot>

Silverlight XamlReaderクラスはこの文字列を読み込めません。特定のデフォルトの名前空間が必要です:

<z:Zot 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:z="clr-namespace:A.B;assembly=A"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</z:Zot>

(WPF XamlReaderは、この厄介な動作を表示しません)

元の形式のXML文字列は、元の形式でデータベースに保存されます。それらを後者の形式に変換し、文字列としてシリアル化する方法が必要です。

これを達成するための最も簡単な方法に関する提案はありますか?

4

5 に答える 5

1

これは、Python SAX フィルターを使用した私のクラックです。

インポート システム、文字列

from xml.sax import saxutils, handler, make_parser

最初の要素 = True

クラス ContentGenerator(handler.ContentHandler):

    def __init__(self, out = sys.stdout):
        handler.ContentHandler.__init__(self)
        self._out = アウト

    def startDocument(self):
        合格

    def startElement (自己、名前、属性):
        グローバルな最初の要素
        最初の要素の場合:
            属性 = dict(属性)
            名前 = "z:" + 名前
            attrs の「xmlns」の場合:
                attrs['xmlns:z'] = attrs['xmlns']
            attrs['xmlns'] = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            最初の要素 = False
        elif ':' が名前にありません:
            名前 = "z:" + 名前
        self._out.write('<' + 名前)
        for (name, value) in attrs.items():
            self._out.write(' %s="%s"' % (名前, saxutils.escape(値)))
        self._out.write('>')

    def endElement(自己、名前):
        名前に「:」がない場合:
            名前 = "z:" + 名前
        self._out.write('</%s>' % 名前)

    定義文字 (自己、内容):
        self._out.write(saxutils.escape(コンテンツ))

    def ignorableWhitespace (自己、コンテンツ):
        self._out.write(コンテンツ)

    def processingInstruction(自己、ターゲット、データ):
        self._out.write('<?%s %s?>' % (対象、データ))

パーサー = make_parser()
parser.setContentHandler(ContentGenerator())
parser.parse(sys.argv[1])

最初の要素にジャンプし、属性をいじくり回し、ドキュメントの残りの部分でデフォルトの名前空間を持つすべての要素を探し続けます。ただし、ドキュメントに複数の xmlns="" 属性が散りばめられているというコメントは、これには何らかの助けが必要であることを意味します。一般的な手法はそれほど悪くありません。SAX パイプラインは私たちの友人です :-)。

于 2009-04-05T02:59:42.437 に答える
0

これはあまり役に立たないかもしれませんが、読者が根本的に壊れていると言ったようです。使用される名前空間プレフィックスは、属性値がQNAmesである場合に適切にバインドされる必要があることを除いて、重要ではありません。

于 2009-04-04T04:56:54.083 に答える
0

これは役立つかもしれません。

    using System;
    using System.Linq;
    using System.Collections;
    using System.Collections.Generic;
    using System.Xml;
    using System.Xml.Linq;

    public class MainClass 
    {
        public static void Main() 
        {
            XNamespace nameSpace = "http://www.microsoft.com";

            XElement xBooks = new XElement(nameSpace + "Books",
              new XAttribute(XNamespace.Xmlns + "linqdev", nameSpace),
            new XElement(nameSpace + "BookParticipant"));

            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(xBooks.ToString());
            xdoc.Save("c:\\xmloutput.xml");

        }
    }

これは次のように出力されます(XmlDocument xdocから、XmlDocument行は実際には必要ありませんが、使用法を示すために例に含めただけです)。

<linqdev:Books xmlns:linqdev="http://www.microsoft.com">
  <linqdev:BookParticipant />
</linqdev:Books> 

いくつかのxml読み取り手法を使用して、元の文字列から他の名前空間を引き出し、上記の手法を使用して新しい文字列を作成できます。

于 2009-04-04T05:05:26.620 に答える
0

私が思いついた最高のものは、デフォルトのxmlns属性を持つ要素に異なる名前空間プレフィックスを与えるスタイルシートでした。私のドキュメントには複数のxmlns="..."属性があるため、これはツリーの下で再帰的に適用されます。

それが他の誰かに役立つ場合のために、ここにあります...私のXSLスキルは主にグーグルに基づいていますが:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:ms="urn:schemas-microsoft-com:xslt"   
    >
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>    

    <xsl:variable name="root_default_ns" select="namespace-uri(/*)" />

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


    <xsl:template match="*">
        <xsl:param name="old_default_ns" select="$root_default_ns"/>
        <xsl:param name="new_default_ns" />

        <!-- match any element in the source default namespace -->
    <xsl:if test="namespace-uri() = $old_default_ns">
          <xsl:element name="ns_{$new_default_ns}:{local-name()}" namespace="{$old_default_ns}">
              <xsl:copy-of select="@*"/>
               <xsl:apply-templates select="node() | text()">
                   <xsl:with-param name="old_default_ns" select="$old_default_ns" />
                   <xsl:with-param name="new_default_ns" select="$new_default_ns" />
           </xsl:apply-templates>
          </xsl:element>
        </xsl:if>

        <!-- match any element with a prefix qualified namespace -->
        <xsl:if test="namespace-uri() != $old_default_ns and contains(name(), ':')"> 
          <xsl:element name="{name()}" namespace="{namespace-uri()}">
               <xsl:copy-of select="@*"/>
               <xsl:apply-templates select="node() | text()">
                   <xsl:with-param name="old_default_ns" select="$old_default_ns" />
                   <xsl:with-param name="new_default_ns" select="$new_default_ns" />
           </xsl:apply-templates>
          </xsl:element>
    </xsl:if>

        <!-- match any element *without* a prefix qualified namespace -->
        <xsl:if test="namespace-uri() != $old_default_ns and contains(name(), ':') = false"> 
      <xsl:variable name="new_ns" select="count(ancestor::*)" />

          <xsl:element name="ns_{$new_ns}:{name()}" namespace="{namespace-uri()}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
               <xsl:copy-of select="@*"/>
               <xsl:apply-templates select="node() | text()">
                   <xsl:with-param name="old_default_ns" select="namespace-uri()" />
                   <xsl:with-param name="new_default_ns"><xsl:value-of select="$new_ns" /></xsl:with-param>
           </xsl:apply-templates>
          </xsl:element>
        </xsl:if>

    </xsl:template>

    <!-- match root element only, and inject Silverlight namespace -->
    <xsl:template match="/*">
       <xsl:element name="ns_root:{local-name()}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" namespace="{$root_default_ns}">
          <!-- inject the Silverligth ns -->
         <xsl:variable name="dummy">
           <Dummy/>
         </xsl:variable>
         <xsl:copy-of select="ms:node-set($dummy)/*/namespace::*"/>
         <xsl:copy-of select="@*"/>
         <xsl:apply-templates select="node() | text()">
           <xsl:with-param name="old_default_ns" select="$root_default_ns" />
           <xsl:with-param name="new_default_ns">root</xsl:with-param>
         </xsl:apply-templates>
      </xsl:element>
    </xsl:template>

 </xsl:stylesheet>

残念ながら、このフープをジャンプした後、XamlReaderが期待する規則に準拠するXAML文字列を取得しますが、代わりにSystem.ExecutionEngineExceptionを生成します(WPF XamlReaderは引き続き文字列を正常に処理します)

于 2009-04-05T00:17:32.687 に答える
0

たぶん、これを使用できます: http://www.cnblogs.com/sheva/archive/2006/08/28/488915.html

于 2009-04-14T20:42:31.220 に答える