Lire et écrire des données XML à l'aide de la bibliothèque spark-xml
Cette documentation a été retirée et pourrait ne pas être mise à jour. Les produits, services ou technologies mentionnés dans ce contenu ne sont pas officiellement approuvés ou testés par Databricks.
Alternativement, la prise en charge native du format de fichier XML est disponible en Public Preview. Voir Lire et écrire des fichiers XML.
Cet article décrit comment lire et écrire un fichier XML en tant que source de données Apache Spark.
Exigences
-
Créez la bibliothèque
spark-xmlen tant que bibliothèque Maven. Pour la coordonnée Maven, spécifiez :- Databricks Runtime 7.x et versions supérieures :
com.databricks:spark-xml_2.12:<release>
Consultez les versions de
spark-xmlpour la dernière version de<release>. - Databricks Runtime 7.x et versions supérieures :
-
Installez la bibliothèque sur un cluster.
Exemple
L'exemple de cette section utilise le fichier XML books.
-
Récupérez le fichier XML des livres :
Bash$ wget https://github.com/databricks/spark-xml/raw/master/src/test/resources/books.xml -
Téléchargez le fichier vers DBFS.
Lire et écrire des données XML
- SQL
- Scala
- R
/*Infer schema*/
CREATE TABLE books
USING xml
OPTIONS (path "dbfs:/books.xml", rowTag "book")
/*Specify column names and types*/
CREATE TABLE books (author string, description string, genre string, _id string, price double, publish_date string, title string)
USING xml
OPTIONS (path "dbfs:/books.xml", rowTag "book")
// Infer schema
import com.databricks.spark.xml._ // Add the DataFrame.read.xml() method
val df = spark.read
.option("rowTag", "book")
.xml("dbfs:/books.xml")
val selectedData = df.select("author", "_id")
selectedData.write
.option("rootTag", "books")
.option("rowTag", "book")
.xml("dbfs:/newbooks.xml")
// Specify schema
import org.apache.spark.sql.types.{StructType, StructField, StringType, DoubleType}
val customSchema = StructType(Array(
StructField("_id", StringType, nullable = true),
StructField("author", StringType, nullable = true),
StructField("description", StringType, nullable = true),
StructField("genre", StringType, nullable = true),
StructField("price", DoubleType, nullable = true),
StructField("publish_date", StringType, nullable = true),
StructField("title", StringType, nullable = true)))
val df = spark.read
.option("rowTag", "book")
.schema(customSchema)
.xml("books.xml")
val selectedData = df.select("author", "_id")
selectedData.write
.option("rootTag", "books")
.option("rowTag", "book")
.xml("dbfs:/newbooks.xml")
# Infer schema
library(SparkR)
sparkR.session("local[4]", sparkPackages = c("com.databricks:spark-xml_2.12:<release>"))
df <- read.df("dbfs:/books.xml", source = "xml", rowTag = "book")
# Default `rootTag` and `rowTag`
write.df(df, "dbfs:/newbooks.xml", "xml")
# Specify schema
customSchema <- structType(
structField("_id", "string"),
structField("author", "string"),
structField("description", "string"),
structField("genre", "string"),
structField("price", "double"),
structField("publish_date", "string"),
structField("title", "string"))
df <- read.df("dbfs:/books.xml", source = "xml", schema = customSchema, rowTag = "book")
# In this case, `rootTag` is set to "ROWS" and `rowTag` is set to "ROW".
write.df(df, "dbfs:/newbooks.xml", "xml", "overwrite")
Options
-
Lire l'article
-
path: Emplacement des fichiers XML. Accepte les expressions glob Hadoop standard. -
rowTag: La balise de ligne à traiter comme une ligne. Par exemple, dans ce code XML<books><book><book>...</books>, la valeur seraitbook. La valeur par default estROW. -
samplingRatio: Taux d'échantillonnage pour l'inférence de schéma (0,0 à 1). default is 1. Les types possibles sontStructType,ArrayType,StringType,LongType,DoubleType,BooleanType,TimestampTypeetNullType, à moins que vous ne fournissiez un schéma. -
excludeAttribute: Si les attributs doivent être exclus des éléments. La valeur par default est false. -
nullValue: La valeur à traiter comme une valeurnull. La valeur par default est"". -
mode: Le mode pour gérer les enregistrements corrompus. default estPERMISSIVE.-
PERMISSIVE:- Lorsqu'il rencontre un enregistrement corrompu, il définit tous les champs sur
nullet place la chaîne malformée dans un nouveau champ configuré parcolumnNameOfCorruptRecord. - Lorsqu'il rencontre un champ du mauvais type de données, il définit le champ incriminé sur
null.
- Lorsqu'il rencontre un enregistrement corrompu, il définit tous les champs sur
-
DROPMALFORMED: ignore les enregistrements corrompus. -
FAILFAST: lève une exception lorsqu’il détecte des enregistrements corrompus.
-
-
inferSchema: sitrue, tente d'inférer un type approprié pour chaque colonne DataFrame résultante, comme un type booléen, numérique ou de date. Sifalse, toutes les colonnes résultantes sont de type chaîne de caractères. La valeur par default esttrue. -
columnNameOfCorruptRecord: le nom du nouveau champ où les chaînes mal formées sont stockées. default est_corrupt_record. -
attributePrefix: Le préfixe des attributs afin de différencier les attributs et les éléments. C'est le préfixe pour les noms de champ. default est_. -
valueTag: Le tag utilisé pour la valeur lorsqu'il y a des attributs dans un élément qui n'a pas d'éléments enfants. default est_VALUE. -
charset: default àUTF-8mais peut être défini sur d'autres noms de jeu de caractères valides. -
ignoreSurroundingSpaces: si les espaces blancs entourant les valeurs doivent être ignorés. La valeur par default est false. -
rowValidationXSDPath: Chemin d'accès à un fichier XSD utilisé pour valider le XML de chaque ligne. Les lignes qui ne parviennent pas à valider sont traitées comme des erreurs d'analyse, comme ci-dessus. Le XSD n'affecte pas le schéma fourni ou inféré. Si le même chemin local n'est pas déjà visible sur les exécuteurs du cluster, alors le XSD et tout autre élément dont il dépend devraient être ajoutés aux exécuteurs Spark avec SparkContext.addFile. Dans ce cas, pour utiliser le XSD local/foo/bar.xsd, appelezaddFile("/foo/bar.xsd")et transmettez"bar.xsd"en tant querowValidationXSDPath.
-
-
Écriture
path: emplacement pour écrire des fichiers.rowTag: La balise de ligne à traiter comme une ligne. Par exemple, dans ce code XML<books><book><book>...</books>, la valeur seraitbook. La valeur par default estROW.rootTag: La balise racine à traiter comme la racine. Par exemple, dans ce code XML<books><book><book>...</books>, la valeur seraitbooks. La valeur par default estROWS.nullValue: La valeur à écrirenullvaleur. La valeur par default est la chaîne"null". Lorsque"null", il n'écrit pas d'attributs et d'éléments pour les champs.attributePrefix: Le préfixe pour les attributs afin de différencier les attributs et les éléments. C'est le préfixe pour les noms de champ. default est_.valueTag: Le tag utilisé pour la valeur lorsqu'il y a des attributs dans un élément qui n'a pas d'éléments enfants. default est_VALUE.compression: Codec de compression à utiliser lors de l'enregistrement dans un fichier. Doit être le nom entièrement qualifié d'une classe implémentantorg.apache.hadoop.io.compress.CompressionCodecou l'un des noms courts insensibles à la casse (bzip2,gzip,lz4etsnappy). Par default, il n'y a pas de compression.
Prend en charge l'utilisation du nom raccourci ; Vous pouvez utiliser xml au lieu de com.databricks.spark.xml.
Prise en charge de XSD
Vous pouvez valider des lignes individuelles par rapport à un schéma XSD à l'aide de rowValidationXSDPath.
Vous utilisez l'utilitaire com.databricks.spark.xml.util.XSDToSchema pour extraire un schéma de DataFrame Spark
à partir de certains fichiers XSD. Il prend en charge uniquement les types simples, complexes et de séquence, uniquement les fonctionnalités XSD de base,
et est expérimental.
import com.databricks.spark.xml.util.XSDToSchema
import java.nio.file.Paths
val schema = XSDToSchema.read(Paths.get("/path/to/your.xsd"))
val df = spark.read.schema(schema)....xml(...)
Analysez un XML imbriqué
Bien que principalement utilisée pour convertir un fichier XML en DataFrame, vous pouvez également utiliser la méthode from_xml pour analyser le XML dans une colonne de type chaîne dans un DataFrame existant et l'ajouter comme nouvelle colonne avec les résultats analysés sous forme de struct avec :
import com.databricks.spark.xml.functions.from_xml
import com.databricks.spark.xml.schema_of_xml
import spark.implicits._
val df = ... /// DataFrame with XML in column 'payload'
val payloadSchema = schema_of_xml(df.select("payload").as[String])
val parsed = df.withColumn("parsed", from_xml($"payload", payloadSchema))
-
mode:- S'il est défini sur
PERMISSIVE, default, le mode d'analyse utilise par défautDROPMALFORMED. Si vous incluez une colonne dans le schéma defrom_xmlqui correspond àcolumnNameOfCorruptRecord, le modePERMISSIVEgénère des enregistrements mal formés pour cette colonne dans la structure résultante. - Si défini sur
DROPMALFORMED, les valeurs XML qui ne sont pas analysées correctement donnent une valeurnullpour la colonne. Aucune ligne n'est supprimée.
- S'il est défini sur
-
from_xmlconvertit les tableaux de chaînes contenant du XML en tableaux de structs analysées. Utilisezschema_of_xml_arrayau lieu de. -
from_xml_stringest une alternative à utiliser dans les UDF qui opère directement sur une chaîne de caractères au lieu d'une colonne.
Règles de conversion
En raison des différences structurelles entre les DataFrames et le XML, il existe des règles de conversion des données XML en DataFrame et des données DataFrame en données XML. Vous pouvez désactiver le traitement des attributs avec l'option excludeAttribute.
Convertir XML en DataFrame
-
Attributs : Les attributs sont convertis en champs avec le préfixe spécifié dans l'option
attributePrefix. SiattributePrefixest_, le documentXML<one myOneAttrib="AAAA">
<two>two</two>
<three>three</three>
</one>produit le schéma :
root
|-- _myOneAttrib: string (nullable = true)
|-- two: string (nullable = true)
|-- three: string (nullable = true) -
Si un élément a des attributs mais pas d'éléments enfants, la valeur de l'attribut est placée dans un champ séparé spécifié dans l'option
valueTag. SivalueTagest_VALUE, le documentXML<one>
<two myTwoAttrib="BBBBB">two</two>
<three>three</three>
</one>produit le schéma :
root
|-- two: struct (nullable = true)
| |-- _VALUE: string (nullable = true)
| |-- _myTwoAttrib: string (nullable = true)
|-- three: string (nullable = true)
Convertir un DataFrame en XML
L'écriture d'un fichier XML à partir d'un DataFrame ayant un champ ArrayType avec son élément comme ArrayType aurait un champ imbriqué supplémentaire pour l'élément. Cela ne se produirait pas lors de la lecture et de l'écriture de données XML, mais lors de l'écriture d'un DataFrame lu à partir d'autres sources. Par conséquent, l'aller-retour en lecture et écriture de fichiers XML a la même structure, mais il est possible qu'un DataFrame lu à partir d'autres sources ait une structure différente lors de l'écriture.
Un DataFrame avec le schéma :
|-- a: array (nullable = true)
| |-- element: array (containsNull = true)
| | |-- element: string (containsNull = true)
et données :
+------------------------------------+
| a|
+------------------------------------+
|[WrappedArray(aa), WrappedArray(bb)]|
+------------------------------------+
produit le fichier XML :
<a>
<item>aa</item>
</a>
<a>
<item>bb</item>
</a>