6

JAXPを使用してxmlドキュメントを作成し、スキーマロケーションを挿入する方法を検索します。現時点では、私のアプリケーションは以下を生成します。

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

しかし、私は必要です:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="namespaceURL" 
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="namespaceURL pathToMySchema.xsd">
...
</root>

私のコード:

StreamResult result = new StreamResult(writer);
Document doc = getDocument();

Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.METHOD, "xml");
trans.setOutputProperty(OutputKeys.VERSION, "1.0");
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

DOMSource source = new DOMSource(depl.getAsElement(doc));
trans.transform(source, result);

お時間をいただきありがとうございます、
Kasten

4

3 に答える 3

6

XMLデータモデルでは、名前空間ノードは実際には親要素から読み取られませんが、各要素には独自の名前空間ノードがあります。したがって、ルート要素に新しいデフォルトの名前空間を追加するだけでは機能しませんが、次のようなドキュメントになります

<root xmlns="namespaceURL">
    <child xmlns=""/>
    ...
</root>

xmlns=""子要素に空のデフォルトの名前空間が表示されていることに注意してください。実際に行う必要があるのは、すべてのノードの名前空間を変更するか、目的のデフォルトの名前空間で新しいドキュメントを作成し、古いドキュメントの内容、要素、属性名などを新しいドキュメントにコピーすることです。これらは、元のドキュメントを再帰的に調べることで実行できます。Java DOMの実装では、これは面倒な作業になる可能性があると聞いています。ショートカットの1つは、名前空間を認識しないDOMを使用してドキュメントを読み取り、新しいデフォルトの名前空間を属性として追加することです。他の解決策は、XSLT変換を使用して名前空間を変更することです。これは、実際にはXSLT変換を介して出力を既に生成しているため、この場合は非常に適しているようです。

このXSLTスタイルシートを使用して、新しいデフォルトの名前空間とスキーマの場所をルート要素に追加します。このスタイルシートは古い名前空間を保持しますが、以前は名前空間がなかった場合は、すべての要素を新しいデフォルトの名前空間に追加します。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

    <!-- Template to add a default namespace to a document -->
    <!-- Elements without a namespace are "moved" to default namespace -->
    <!-- Elements with a namespace are copied as such -->

  <!-- string for default namespace uri and schema location -->
  <xsl:variable name="ns" select="'namespaceURL'"/>
  <xsl:variable name="schemaLoc" select="'namespaceURL pathToMySchema.xsd'"/>

    <!-- template for root element -->
    <!-- adds default namespace and schema location -->
  <xsl:template match="/*" priority="1">
    <xsl:element name="{local-name()}" namespace="{$ns}">
      <xsl:attribute name="xsi:schemaLocation"
        namespace="http://www.w3.org/2001/XMLSchema-instance">
        <xsl:value-of select="$schemaLoc"/>
        </xsl:attribute>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

    <!--template for elements without a namespace -->
  <xsl:template match="*[namespace-uri() = '']">
    <xsl:element name="{local-name()}" namespace="{$ns}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

    <!--template for elements with a namespace -->
  <xsl:template match="*[not(namespace-uri() = '')]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

    <!--template to copy attributes, text, PIs and comments -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

でトランスフォーマーを作成する代わりに

Transformer trans = transfac.newTransformer();

(ID変換を行うスタイルシートを作成します)、XSLT入力ソースを作成し、それをパラメーターとしてnewTransformer()

javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
Transformer trans = transFact.newTransformer(xsltSource);

ここで、xsltFileFileそのXSLTファイルを指すオブジェクトです。

transform()必要に応じて出力プロパティを設定し、サンプルコードのように呼び出します。結果はあなたが望むものになるはずですが、私はこれをJavaでテストしていません。指定されたXSLTファイルは、いくつかの些細なケースでテストされており、この回答の最後にサンプルの入力と出力があります。

いくつかのマイナーな注意:

  1. このプロセスでは、元のドキュメントオブジェクトは変更されません。新しいデフォルトの名前空間は、transform()メソッドの出力にのみ表示されます。
  2. スキーマインスタンス名前空間の名前空間プレフィックスは通常、サンプルコードのようにでxsi:はありません(スキーマ定義(および)で使用されます)。xs:xs:xsd:

上記のXSLTスタイルシートの入力と出力の例

入力:

<root>
    <child>text</child>
    <child attribute="attr-value"/>
    <?pi-target pi-content?>
    <nsx:ns-child xmlns:nsx="ns1x">
        <no-ns-child>text</no-ns-child>
        <!-- comment -->
        <nsx:ns-child nsx:ns-attribute="nsx-attr-value">text</nsx:ns-child>
    </nsx:ns-child>
    <defns-child xmlns="default-ns">
        <def-child attr="val">text</def-child>
        <child xmlns=""/>
    </defns-child>
    <child>text</child>
</root>

出力:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="namespaceURL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="namespaceURL pathToMySchema.xsd">
    <child>text</child>
    <child attribute="attr-value"/>
    <?pi-target pi-content?>
    <nsx:ns-child xmlns:nsx="ns1x">
        <no-ns-child>text</no-ns-child>
        <!-- comment -->
        <nsx:ns-child nsx:ns-attribute="nsx-attr-value">text</nsx:ns-child>
    </nsx:ns-child>
    <defns-child xmlns="default-ns">
        <def-child attr="val">text</def-child>
        <child xmlns="namespaceURL"/>
    </defns-child>
    <child>text</child>
</root>
于 2011-02-09T23:42:39.757 に答える
6

ドキュメントの作成時に、ルートに名前空間を追加できます。

String NS_URL = "namespaceURL";

doc = builder.newDocument();
Element root = doc.createElementNS(NS_URL, "root");
root.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", 
    "xs:schemaLocation", NS_URL + " pathToMySchema.xsd");
doc.appendChild(root);

次に、createElement()の代わりにドキュメントに追加された要素ごとにcreateElementNS()を使用します

doc.createElementNS(NS_URL, name);

これはあなたが探していたものになります。

<root 
    xmlns="namespaceURL"
    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 
    xs:schemaLocation="namespaceURL pathToMySchema.xsd"
    >
于 2012-07-31T09:37:25.073 に答える
1

問題を解決するためにパーサーにヒントを与える方法は次のとおりです。http: //bytes.com/topic/java/answers/16892-xerces-how-perfrom-schema-validations-without-using-xsi-schemalocation

こんなふうになります:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(true);
dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLocation",
"http://www.example.com/Report.xsd");

これは、いくつかのソースコードを使用した検証例です。それはあなたを助けるかもしれません。 http://www.ibm.com/developerworks/xml/library/x-tipvalschm/

(すべてが悪化した場合は、いつでも検索して置換できます。これが理想的なソリューションではないことはわかっていますが、javax.xml.transform.OutputKeysにはschemalocation属性に関連するメンバーがないようです。)

于 2011-02-08T14:21:25.507 に答える