4

特定のXMLファイルからすべての名前空間情報を取得できるようにしたい。

たとえば、入力XMLファイルが次のようなものである場合:

<ns1:create xmlns:ns1="http://predic8.com/wsdl/material/ArticleService/1/">
   <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
      <ns1:id>1</ns1:id>
      <description>bar</description>
      <name>foo</name>
      <ns1:price>
         <amount>00.00</amount>
         <currency>USD</currency>
      </ns1:price>
      <ns1:price>
         <amount>11.11</amount>
         <currency>AUD</currency>
      </ns1:price>
   </ns1:article>
   <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
      <ns1:id>2</ns1:id>
      <description>some name</description>
      <name>some description</name>
      <ns1:price>
         <amount>00.01</amount>
         <currency>USD</currency>
      </ns1:price>
   </ns1:article>
</ns1:create>

次のような出力を期待したいと思います(この場合はコンマ区切り):

create, ns1, http://predic8.com/wsdl/material/ArticleService/1/
article, ns1, http://predic8.com/material/1/
price, ns1, http://predic8.com/material/1/
id, ns1, http://predic8.com/material/1/

重要な注意事項:

特定の名前空間内で定義されているが、その定義が上位ノードで定義されている可能性があるサブノードも考慮することが重要です。たとえば、ノードを取得したい場合はns1:id、親ノードまでさかのぼってns1:article名前空間のURLが次のようになっていることを確認する必要があります。xmlns:ns1='http://predic8.com/material/1/

私はJavaで実装しているので、Javaベースのソリューションでも、XSLTベースのソリューションでも適切と思われるかもしれません。

4

3 に答える 3

6

これは、単一のXPath2.0式で実行できます。

distinct-values(//*[name()!=local-name()]/
   concat(local-name(), ', ', substring-before(name(), ':'), ', ', namespace-uri())
于 2012-07-11T21:33:13.133 に答える
5

組み込みのXMLStreamReaderを使用します。これは、ストリーミングXMLパーサーによって実装されるインターフェイスです(XMLInputFactoryクラスから取得します)。そのgetNameメソッドはQNameを返します。これにより、必要なものがすべて提供されます。

次のようなもの:

File file = new File("samples/sample11.xml");
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLStreamReader reader = inputFactory.createXMLStreamReader(new FileInputStream(file));
Set<String> namespaces = new HashSet<String>();
while (reader.hasNext()) {
      int evt = reader.next();
      if (evt == XMLStreamConstants.START_ELEMENT) {
        QName qName = reader.getName();
        if(qName != null){
            if(qName.getPrefix() != null && qName.getPrefix().compareTo("")!=0)
                namespaces.add(String.format("%s, %s, %s",
                    qName.getLocalPart(), qName.getPrefix(), qName.getNamespaceURI()));
        }
      }
}

for(String namespace : namespaces){
    System.out.println(namespace);              
}
于 2012-07-11T17:15:12.640 に答える
4

Michael Kayによって提案されたXPath式をさらに開発し(実際には単純化したように見えます)、デフォルトの名前空間に属する接頭辞なしの要素名も処理します。

distinct-values(//*[namespace-uri()]
                    /concat(local-name(),
                            ', ',
                            substring-before(name(), ':'),
                            ', ',
                            namespace-uri(),
                            '&#xA;'
                            )
                )

このXPath式が次のドキュメントで評価される場合(提供されているが、デフォルトの名前空間にある要素が追加されている):

<ns1:create xmlns:ns1="http://predic8.com/wsdl/material/ArticleService/1/">
    <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
        <ns1:id>1</ns1:id>
        <description>bar</description>
        <name>foo</name>
        <ns1:price>
            <amount>00.00</amount>
            <currency>USD</currency>
        </ns1:price>
        <ns1:price>
            <amount>11.11</amount>
            <currency>AUD</currency>
        </ns1:price>
    </ns1:article>
    <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
        <ns1:id>2</ns1:id>
        <description>some name</description>
        <name>some description</name>
        <ns1:price>
            <amount>00.01</amount>
            <currency>USD</currency>
        </ns1:price>
        <quality xmlns="my:q">high</quality>
    </ns1:article>
</ns1:create>

必要な正しい結果が生成されます:

 create, ns1, http://predic8.com/wsdl/material/ArticleService/1/
 article, ns1, xmlns:ns1='http://predic8.com/material/1/
 id, ns1, xmlns:ns1='http://predic8.com/material/1/
 price, ns1, xmlns:ns1='http://predic8.com/material/1/
 quality, , my:q

さらに、わずかな改善として、属性名の名前空間データを生成することもできます。

distinct-values(//(*|@*)[namespace-uri()]
                    /concat(if(. intersect ../@*)
                              then '@'
                              else (),
                            local-name(),
                            ', ',
                            substring-before(name(), ':'),
                            ', ',
                            namespace-uri(),
                            '&#xA;'
                            )
                )

このXPath式が次のXMLドキュメント(要素xml:langの1つに属性が追加された前のドキュメント(上記))で評価される場合:article

<ns1:create xmlns:ns1="http://predic8.com/wsdl/material/ArticleService/1/">
    <ns1:article xml:lang="en-us" xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
        <ns1:id>1</ns1:id>
        <description>bar</description>
        <name>foo</name>
        <ns1:price>
            <amount>00.00</amount>
            <currency>USD</currency>
        </ns1:price>
        <ns1:price>
            <amount>11.11</amount>
            <currency>AUD</currency>
        </ns1:price>
    </ns1:article>
    <ns1:article xmlns:ns1="xmlns:ns1='http://predic8.com/material/1/">
        <ns1:id>2</ns1:id>
        <description>some name</description>
        <name>some description</name>
        <ns1:price>
            <amount>00.01</amount>
            <currency>USD</currency>
        </ns1:price>
        <quality xmlns="my:q">high</quality>
    </ns1:article>
</ns1:create>

ここでも正しい結果が生成されます。

 create, ns1, http://predic8.com/wsdl/material/ArticleService/1/
 article, ns1, xmlns:ns1='http://predic8.com/material/1/
 @lang, xml, http://www.w3.org/XML/1998/namespace
 id, ns1, xmlns:ns1='http://predic8.com/material/1/
 price, ns1, xmlns:ns1='http://predic8.com/material/1/
 quality, , my:q
于 2012-07-12T04:18:38.497 に答える